/*++ /* NAME /* valid_hostname 3 /* SUMMARY /* network name validation /* SYNOPSIS /* #include <valid_hostname.h> /* /* int valid_hostname(name, flags) /* const char *name; /* int flags; /* /* int valid_hostaddr(addr, gripe) /* const char *addr; /* int gripe; /* /* int valid_ipv4_hostaddr(addr, gripe) /* const char *addr; /* int gripe; /* /* int valid_ipv6_hostaddr(addr, gripe) /* const char *addr; /* int gripe; /* /* int valid_hostport(port, gripe) /* const char *port; /* int gripe; /* DESCRIPTION /* valid_hostname() scrutinizes a hostname: the name should /* be no longer than VALID_HOSTNAME_LEN characters, should /* contain only letters, digits, dots and hyphens, no adjacent /* dots, no leading or trailing dots or hyphens, no labels /* longer than VALID_LABEL_LEN characters, and it should not /* be all numeric. /* The flags argument is the bit-wise or of zero or more of /* DO_GRIPE or DO_WILDCARD (the latter allows the "*." name /* prefix, which is rare but valid in some DNS responses and /* queries). /* /* valid_hostaddr() requires that the input is a valid string /* representation of an IPv4 or IPv6 network address as /* described next. /* /* valid_ipv4_hostaddr() and valid_ipv6_hostaddr() implement /* protocol-specific address syntax checks. A valid IPv4 /* address is in dotted-quad decimal form. A valid IPv6 address /* has 16-bit hexadecimal fields separated by ":", and does not /* include the RFC 2821 style "IPv6:" prefix. /* /* These routines operate silently unless the gripe parameter /* specifies a non-zero value. The macros DO_GRIPE and DONT_GRIPE /* provide suitable constants. /* /* valid_hostport() requires that the input is a valid string /* representation of a TCP or UDP port number. /* BUGS /* valid_hostmumble() does not guarantee that string lengths /* fit the buffer sizes defined in myaddrinfo(3h). /* DIAGNOSTICS /* All functions return zero if they disagree with the input. /* SEE ALSO /* RFC 952, RFC 1123, RFC 1035, RFC 2373. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA
/*--*/
int valid_hostname(constchar *name, int flags)
{ constchar *myname = "valid_hostname"; constchar *cp; int label_length = 0; int label_count = 0; int non_numeric = 0; int ch; int gripe = flags & DO_GRIPE;
/* *Trivialcasesfirst.
*/ if (*name == 0) { if (gripe)
msg_warn("%s: empty hostname", myname); return (0);
}
/* valid_ipv4_hostaddr - test dotted quad string for correctness */
int valid_ipv4_hostaddr(constchar *addr, int gripe)
{ constchar *cp; constchar *myname = "valid_ipv4_hostaddr"; int in_byte = 0; int byte_count = 0; int byte_val = 0; int ch;
#define BYTES_NEEDED 4
/* *Scarycodetoavoidsscanf()overflownasties. * *Thisroutineiscalledbyvalid_ipv6_hostaddr().Itmustnotcallthat *routine,toavoiddeadlyrecursion.
*/ for (cp = addr; (ch = *(unsignedconstchar *) cp) != 0; cp++) { if (ISDIGIT(ch)) { if (in_byte == 0) {
in_byte = 1;
byte_val = 0;
byte_count++;
}
byte_val *= 10;
byte_val += ch - '0'; if (byte_val > 255) { if (gripe)
msg_warn("%s: invalid octet value: %.100s", myname, addr); return (0);
}
} elseif (ch == '.') { if (in_byte == 0 || cp[1] == 0) { if (gripe)
msg_warn("%s: misplaced dot: %.100s", myname, addr); return (0);
} /* XXX Allow 0.0.0.0 but not 0.1.2.3 */ if (byte_count == 1 && byte_val == 0 && addr[strspn(addr, "0.")]) { if (gripe)
msg_warn("%s: bad initial octet value: %.100s", myname, addr); return (0);
}
in_byte = 0;
} else { if (gripe)
msg_warn("%s: invalid character %d(decimal): %.100s",
myname, ch, addr); return (0);
}
}
if (byte_count != BYTES_NEEDED) { if (gripe)
msg_warn("%s: invalid octet count: %.100s", myname, addr); return (0);
} return (1);
}
int valid_ipv6_hostaddr(constchar *addr, int gripe)
{ constchar *myname = "valid_ipv6_hostaddr"; int null_field = 0; int field = 0; unsignedchar *cp = (unsignedchar *) addr; int len = 0;
/* *FIX200501TheIPv6patchvalidatedsyntaxwithgetaddrinfo(),butI *amnotconfidentthateveryone'ssystemlibraryroutinesarerobust *enough,likebufferoverflowfree.Remember,thevalid_hostmumble() *routinesaremeanttoprotectPostfixagainstmalformedinformationin *datareceivedfromthenetwork. * *Werequireeight-fieldhexaddressesoftheform0:1:2:3:4:5:6:7, *0:1:2:3:4:5:6a.6b.7c.7d,orsome::compressedversionofthesame. * *Note:thecharacterpositionisadvancedinsidetheloop.Ihaveadded *commentstoshowwhywecan'tgetstuck.
*/ for (;;) { switch (*cp) { case0: /* Terminate the loop. */ if (field < 2) { if (gripe)
msg_warn("%s: too few `:' in IPv6 address: %.100s",
myname, addr); return (0);
} elseif (len == 0 && null_field != field - 1) { if (gripe)
msg_warn("%s: bad null last field in IPv6 address: %.100s",
myname, addr); return (0);
} else return (1); case'.': /* Terminate the loop. */ if (field < 2 || field > 6) { if (gripe)
msg_warn("%s: malformed IPv4-in-IPv6 address: %.100s",
myname, addr); return (0);
} else /* NOT: valid_hostaddr(). Avoid recursion. */ return (valid_ipv4_hostaddr((char *) cp - len, gripe)); case':': /* Advance by exactly 1 character position or terminate. */ if (field == 0 && len == 0 && ISALNUM(cp[1])) { if (gripe)
msg_warn("%s: bad null first field in IPv6 address: %.100s",
myname, addr); return (0);
}
field++; if (field > 7) { if (gripe)
msg_warn("%s: too many `:' in IPv6 address: %.100s",
myname, addr); return (0);
}
cp++;
len = 0; if (*cp == ':') { if (null_field > 0) { if (gripe)
msg_warn("%s: too many `::' in IPv6 address: %.100s",
myname, addr); return (0);
}
null_field = field;
} break; default: /* Advance by at least 1 character position or terminate. */
len = strspn((char *) cp, "0123456789abcdefABCDEF"); if (len /* - strspn((char *) cp, "0") */ > 4) { if (gripe)
msg_warn("%s: malformed IPv6 address: %.100s",
myname, addr); return (0);
} if (len <= 0) { if (gripe)
msg_warn("%s: invalid character %d(decimal) in IPv6 address: %.100s",
myname, *cp, addr); return (0);
}
cp += len; break;
}
}
}
/* valid_hostport - validate numeric port */
int valid_hostport(constchar *str, int gripe)
{ constchar *myname = "valid_hostport"; int port;
if (str[0] == '0' && str[1] != 0) { if (gripe)
msg_warn("%s: leading zero in port number: %.100s", myname, str); return (0);
} if (alldig(str) == 0) { if (gripe)
msg_warn("%s: non-numeric port number: %.100s", myname, str); return (0);
} if (strlen(str) > strlen("65535")
|| (port = atoi(str)) > 65535 || port < 0) { if (gripe)
msg_warn("%s: out-of-range port number: %.100s", myname, str); return (0);
} return (1);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.