*** /tmp/,RCSt1a11672 Mon Sep 29 18:22:57 1997 --- hosts_access.c Mon Aug 11 19:56:16 1997 *************** *** 240,245 **** --- 240,285 ---- } } + #ifdef DO_REGEXPS + /* + * This code uses oldfashioned re_comp/re_exec routines to match + * regular expressions against hostnames. Life would be much simpler + * if we could use POSIX regular expressions, because then we wouldn't + * have to contort ourselves for supporting lower case, but life sucks + * and the POSIX regexp routines aren't available everywhere (especially + * on SunOS 4, where I really want this code). + * - cks + */ + #include + #include + extern char *re_comp(); + + static int regexp_match(re, host) + char *re, *host; + { + char *t, *lchost = strdup(host); + int r; + + if (lchost == 0) { + tcpd_warn("cannot get memory in regexp_match"); + return 0; + } + /* compile (and check for errors) the re */ + t = re_comp(re); + if (t != 0) { + tcpd_warn("regexp compilation failed: %s", t); + free(lchost); + return 0; + } + /* force hostname to lower case */ + for (t = lchost; *t; t++) + *t = (isascii(*t) && isupper(*t)) ? tolower(*t) : *t; + r = re_exec(lchost); + free(lchost); + return (r == 1); /* -1 indicates a failure too */ + } + #endif + /* host_match - match host name and/or address against pattern */ static int host_match(tok, host) *************** *** 275,280 **** --- 315,328 ---- return (strchr(name, '.') == 0 && HOSTNAME_KNOWN(name)); } else if ((mask = split_at(tok, '/')) != 0) { /* net/mask */ return (masked_match(tok, mask, eval_hostaddr(host))); + #ifdef DO_REGEXPS + } else if (tok[0] == '_') { /* regexp matching */ + char *name = eval_hostname(host); + return (HOSTNAME_KNOWN(name) && regexp_match(tok+1, name)); + #else + tcpd_warn("regexp hostname matches disabled"); + return (NO); + #endif } else { /* anything else */ return (string_match(tok, eval_hostaddr(host)) || (NOT_INADDR(tok) && string_match(tok, eval_hostname(host)))); *************** *** 313,318 **** --- 361,367 ---- unsigned long net; unsigned long mask; unsigned long addr; + int t; /* * Disallow forms other than dotted quad: the treatment that inet_addr() *************** *** 322,327 **** --- 371,392 ---- if ((addr = dot_quad_addr(string)) == INADDR_NONE) return (NO); + /* + * Allow CIDRized netmask lengths. + */ + if (strchr(mask_tok, '.') == NULL) { + t = atoi(mask_tok); + if (t > 0 && t < 32) { + net = dot_quad_addr(net_tok); + if (net == INADDR_NONE) { + tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok); + return (NO); + } + mask = htonl(((unsigned long) 0xffffffff) << (32-t)); + return ((addr & mask) == net); + } + } + if ((net = dot_quad_addr(net_tok)) == INADDR_NONE || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) { tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);