/* * Parses a host of the form <address>[:port] * paddr is used to create a list in the order of input * **paddr is the ->next pointer of the last entry (or s->addrs) * *paddr is the variable used to keep track of **paddr between calls * port is the default port to assume */ static const char *get_addresses(pool *p, char *w, server_addr_rec ***paddr, unsigned port) { struct hostent *hep; unsigned long my_addr; server_addr_rec *sar; char *t; int i, is_an_ip_addr; if (*w == 0) return NULL; t = strchr(w, ':'); if (t) { if (strcmp(t + 1, "*") == 0) { port = 0; } else if ((i = atoi(t + 1))) { port = i; } else { return ":port must be numeric"; } *t = 0; } is_an_ip_addr = 0; if (strcmp(w, "*") == 0) { my_addr = htonl(INADDR_ANY); is_an_ip_addr = 1; } else if (strcasecmp(w, "_default_") == 0 || strcmp(w, "255.255.255.255") == 0) { my_addr = DEFAULT_VHOST_ADDR; is_an_ip_addr = 1; } else if ((my_addr = ap_inet_addr(w)) != INADDR_NONE) { is_an_ip_addr = 1; } if (is_an_ip_addr) { sar = ap_pcalloc(p, sizeof(server_addr_rec)); **paddr = sar; *paddr = &sar->next; sar->host_addr.s_addr = my_addr; sar->host_port = port; sar->virthost = ap_pstrdup(p, w); if (t != NULL) *t = ':'; return NULL; } hep = gethostbyname(w); if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, "Cannot resolve host name %s --- ignoring!", w); if (t != NULL) *t = ':'; return NULL; } for (i = 0; hep->h_addr_list[i]; ++i) { sar = ap_pcalloc(p, sizeof(server_addr_rec)); **paddr = sar; *paddr = &sar->next; sar->host_addr = *(struct in_addr *) hep->h_addr_list[i]; sar->host_port = port; sar->virthost = ap_pstrdup(p, w); } if (t != NULL) *t = ':'; return NULL; }
static const char *allow_cmd(cmd_parms *cmd, void *dv, char *from, char *where) { access_dir_conf *d = (access_dir_conf *) dv; allowdeny *a; char *s; if (strcasecmp(from, "from")) return "allow and deny must be followed by 'from'"; a = (allowdeny *) ap_push_array(cmd->info ? d->allows : d->denys); a->x.from = where; a->limited = cmd->limited; if (!strncasecmp(where, "env=", 4)) { a->type = T_ENV; a->x.from += 4; } else if (!strcasecmp(where, "all")) { a->type = T_ALL; } else if ((s = strchr(where, '/'))) { struct in_addr mask; a->type = T_IP; /* trample on where, we won't be using it any more */ *s++ = '\0'; if (!is_ip(where) || (a->x.ip.net.s_addr = ap_inet_addr(where)) == INADDR_NONE) { a->type = T_FAIL; return "syntax error in network portion of network/netmask"; } /* is_ip just tests if it matches [\d.]+ */ if (!is_ip(s)) { a->type = T_FAIL; return "syntax error in mask portion of network/netmask"; } /* is it in /a.b.c.d form? */ if (strchr(s, '.')) { mask.s_addr = ap_inet_addr(s); if (mask.s_addr == INADDR_NONE) { a->type = T_FAIL; return "syntax error in mask portion of network/netmask"; } } else { int i; /* assume it's in /nnn form */ i = atoi(s); if (i > 32 || i <= 0) { a->type = T_FAIL; return "invalid mask in network/netmask"; } mask.s_addr = 0xFFFFFFFFUL << (32 - i); mask.s_addr = htonl(mask.s_addr); } a->x.ip.mask = mask; a->x.ip.net.s_addr = (a->x.ip.net.s_addr & mask.s_addr); /* pjr - This fixes PR 4770 */ } else if (ap_isdigit(*where) && is_ip(where)) { /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */ int shift; char *t; int octet; a->type = T_IP; /* parse components */ s = where; a->x.ip.net.s_addr = 0; a->x.ip.mask.s_addr = 0; shift = 24; while (*s) { t = s; if (!ap_isdigit(*t)) { a->type = T_FAIL; return "invalid ip address"; } while (ap_isdigit(*t)) { ++t; } if (*t == '.') { *t++ = 0; } else if (*t) { a->type = T_FAIL; return "invalid ip address"; } if (shift < 0) { a->type = T_FAIL; return "invalid ip address, only 4 octets allowed"; } octet = atoi(s); if (octet < 0 || octet > 255) { a->type = T_FAIL; return "each octet must be between 0 and 255 inclusive"; } a->x.ip.net.s_addr |= (unsigned int)octet << shift; a->x.ip.mask.s_addr |= 0xFFUL << shift; s = t; shift -= 8; } a->x.ip.net.s_addr = ntohl(a->x.ip.net.s_addr); a->x.ip.mask.s_addr = ntohl(a->x.ip.mask.s_addr); } else { a->type = T_HOST; } return NULL; }