5
/* network name validation
7
/* #include <valid_hostname.h>
9
/* int valid_hostname(name, gripe)
13
/* int valid_hostaddr(addr, gripe)
17
/* int valid_hostliteral(addr, gripe)
21
/* valid_hostname() scrutinizes a hostname: the name should be no
22
/* longer than VALID_HOSTNAME_LEN characters, should contain only
23
/* letters, digits, dots and hyphens, no adjacent dots and hyphens,
24
/* no leading or trailing dots or hyphens, no labels longer than
25
/* VALID_LABEL_LEN characters, and no numeric top-level domain.
27
/* valid_hostaddr() requires that the input is a valid string
28
/* representation of an internet network address.
30
/* valid_hostliteral() requires an address enclosed in [].
32
/* These routines operate silently unless the gripe parameter
33
/* specifies a non-zero value. The macros DO_GRIPE and DONT_GRIPE
34
/* provide suitable constants.
36
/* Both functions return zero if they disagree with the input.
38
/* RFC 952, 1123, RFC 1035
42
/* The Secure Mailer license must be distributed with this software.
45
/* IBM T.J. Watson Research
47
/* Yorktown Heights, NY 10598, USA
56
/* Utility library. */
60
#include "stringops.h"
61
#include "valid_hostname.h"
63
/* valid_hostname - screen out bad hostnames */
65
int valid_hostname(const char *name, int gripe)
67
char *myname = "valid_hostname";
75
* Trivial cases first.
79
msg_warn("%s: empty hostname", myname);
84
* Find bad characters or label lengths. Find adjacent delimiters.
86
for (cp = name; (ch = *(unsigned char *) cp) != 0; cp++) {
87
if (ISALNUM(ch) || ch == '_') { /* grr.. */
88
if (label_length == 0)
91
if (label_length > VALID_LABEL_LEN) {
93
msg_warn("%s: hostname label too long: %.100s", myname, name);
98
} else if (ch == '.') {
99
if (label_length == 0 || cp[1] == 0) {
101
msg_warn("%s: misplaced delimiter: %.100s", myname, name);
105
} else if (ch == '-') {
107
if (label_length == 1 || cp[1] == 0 || cp[1] == '.') {
109
msg_warn("%s: misplaced hyphen: %.100s", myname, name);
114
msg_warn("%s: invalid character %d(decimal): %.100s",
120
if (non_numeric == 0) {
122
msg_warn("%s: numeric hostname: %.100s", myname, name);
123
/* NOT: return (0); this confuses users of the DNS client */
125
if (cp - name > VALID_HOSTNAME_LEN) {
127
msg_warn("%s: bad length %d for %.100s...",
128
myname, (int) (cp - name), name);
134
/* valid_hostaddr - test dotted quad string for correctness */
136
int valid_hostaddr(const char *addr, int gripe)
139
char *myname = "valid_hostaddr";
145
#define BYTES_NEEDED 4
148
* Trivial cases first.
152
msg_warn("%s: empty address", myname);
157
* Preliminary IPV6 support.
159
if (strchr(addr, ':')) {
160
if (*(cp = addr + strspn(addr, ":./0123456789abcdefABCDEF")) != 0) {
162
msg_warn("%s: invalid character %d(decimal): %.100s",
170
* Scary code to avoid sscanf() overflow nasties.
172
for (cp = addr; (ch = *(unsigned const char *) cp) != 0; cp++) {
180
byte_val += ch - '0';
181
if (byte_val > 255) {
183
msg_warn("%s: invalid octet value: %.100s", myname, addr);
186
} else if (ch == '.') {
187
if (in_byte == 0 || cp[1] == 0) {
189
msg_warn("%s: misplaced dot: %.100s", myname, addr);
192
if ((byte_count == 1 && byte_val == 0)) {
194
msg_warn("%s: bad initial octet value: %.100s", myname, addr);
200
msg_warn("%s: invalid character %d(decimal): %.100s",
206
if (byte_count != BYTES_NEEDED) {
208
msg_warn("%s: invalid octet count: %.100s", myname, addr);
214
/* valid_hostliteral - validate address literal */
216
int valid_hostliteral(const char *addr, int gripe)
218
const char *myname = "valid_hostliteral";
224
msg_warn("%s: '[' expected at start: %.100s", myname, addr);
227
if ((last = strchr(addr, ']')) == 0) {
229
msg_warn("%s: ']' expected at end: %.100s", myname, addr);
234
msg_warn("%s: unexpected text after ']': %.100s", myname, addr);
237
if (last >= addr + sizeof(buf)) {
239
msg_warn("%s: too much text: %.100s", myname, addr);
242
strncpy(buf, addr + 1, last - addr - 1);
243
buf[last - addr - 1] = 0;
244
return (valid_hostaddr(buf, gripe));
250
* Test program - reads hostnames from stdin, reports invalid hostnames to
257
#include "vstring_vstream.h"
258
#include "msg_vstream.h"
260
int main(int unused_argc, char **argv)
262
VSTRING *buffer = vstring_alloc(1);
264
msg_vstream_init(argv[0], VSTREAM_ERR);
267
while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
268
msg_info("testing: \"%s\"", vstring_str(buffer));
269
valid_hostname(vstring_str(buffer), DO_GRIPE);
270
valid_hostaddr(vstring_str(buffer), DO_GRIPE);
271
valid_hostliteral(vstring_str(buffer), DO_GRIPE);