diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2003-11-21 18:12:50 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2003-11-21 18:12:50 +0000 |
commit | 664c888f84c96719ac69239aeff21b5cddff4206 (patch) | |
tree | 88b08531fb6e83c502b64a3341dbb7634c7de36b /usr.sbin/httpd | |
parent | 86adfae0e33527eb43cda997ae105e35c1db89f3 (diff) |
Allow and Deny rules with IP addresses outside the class A range
(e.g. 192.168.1.1) where parsed incorrectly on sparc64.
It only affected IP addresses with no netmask definition.
The cause of this was:
a) use of the wrong type -- unsigned long instead of a 32bit value
b) implicit casts from int to unsigned long with sign extension
While doing that fix also some other obvious bugs.
from claudio jeker
Diffstat (limited to 'usr.sbin/httpd')
-rw-r--r-- | usr.sbin/httpd/src/modules/standard/mod_access.c | 41 |
1 files changed, 22 insertions, 19 deletions
diff --git a/usr.sbin/httpd/src/modules/standard/mod_access.c b/usr.sbin/httpd/src/modules/standard/mod_access.c index 41884ca1e24..68dec7aa3d9 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_access.c +++ b/usr.sbin/httpd/src/modules/standard/mod_access.c @@ -82,8 +82,8 @@ typedef struct { union { char *from; struct { - unsigned long net; - unsigned long mask; + struct in_addr net; + struct in_addr mask; } ip; } x; enum allowdeny_type type; @@ -167,14 +167,14 @@ static const char *allow_cmd(cmd_parms *cmd, void *dv, char *from, char *where) } else if ((s = strchr(where, '/'))) { - unsigned long mask; + 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 = ap_inet_addr(where)) == INADDR_NONE) { + || (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"; } @@ -186,24 +186,26 @@ static const char *allow_cmd(cmd_parms *cmd, void *dv, char *from, char *where) } /* is it in /a.b.c.d form? */ if (strchr(s, '.')) { - mask = ap_inet_addr(s); - if (mask == INADDR_NONE) { + 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 */ - mask = atoi(s); - if (mask > 32 || mask <= 0) { + i = atoi(s); + if (i > 32 || i <= 0) { a->type = T_FAIL; return "invalid mask in network/netmask"; } - mask = 0xFFFFFFFFUL << (32 - mask); - mask = htonl(mask); + mask.s_addr = 0xFFFFFFFFUL << (32 - i); + mask.s_addr = htonl(mask.s_addr); } a->x.ip.mask = mask; - a->x.ip.net = (a->x.ip.net & mask); /* pjr - This fixes PR 4770 */ + 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 */ @@ -214,8 +216,8 @@ static const char *allow_cmd(cmd_parms *cmd, void *dv, char *from, char *where) a->type = T_IP; /* parse components */ s = where; - a->x.ip.net = 0; - a->x.ip.mask = 0; + a->x.ip.net.s_addr = 0; + a->x.ip.mask.s_addr = 0; shift = 24; while (*s) { t = s; @@ -234,6 +236,7 @@ static const char *allow_cmd(cmd_parms *cmd, void *dv, char *from, char *where) return "invalid ip address"; } if (shift < 0) { + a->type = T_FAIL; return "invalid ip address, only 4 octets allowed"; } octet = atoi(s); @@ -241,13 +244,13 @@ static const char *allow_cmd(cmd_parms *cmd, void *dv, char *from, char *where) a->type = T_FAIL; return "each octet must be between 0 and 255 inclusive"; } - a->x.ip.net |= octet << shift; - a->x.ip.mask |= 0xFFUL << shift; + 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 = ntohl(a->x.ip.net); - a->x.ip.mask = ntohl(a->x.ip.mask); + a->x.ip.net.s_addr = htonl(a->x.ip.net.s_addr); + a->x.ip.mask.s_addr = htonl(a->x.ip.mask.s_addr); } else { a->type = T_HOST; @@ -315,9 +318,9 @@ static int find_allowdeny(request_rec *r, array_header *a, int method) return 1; case T_IP: - if (ap[i].x.ip.net != INADDR_NONE + if (ap[i].x.ip.net.s_addr != INADDR_NONE && (r->connection->remote_addr.sin_addr.s_addr - & ap[i].x.ip.mask) == ap[i].x.ip.net) { + & ap[i].x.ip.mask.s_addr) == ap[i].x.ip.net.s_addr) { return 1; } break; |