]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Fix parsing of Allow/Deny rules using IP addresses without a netmask;
authorJoe Orton <jorton@apache.org>
Sun, 7 Mar 2004 21:47:14 +0000 (21:47 +0000)
committerJoe Orton <jorton@apache.org>
Sun, 7 Mar 2004 21:47:14 +0000 (21:47 +0000)
issue is known to affect only big-endian 64-bit platforms; on affected
platforms such rules would never produce matches.

PR: 23850
Submitted by: Henning Brauer <henning@openbsd.org>

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x@102879 13f79535-47bb-0310-9956-ffa450edef68

src/CHANGES
src/modules/standard/mod_access.c

index f1fb0db5a7a1c2bed9ff2fae60c9af0eb2b97621..204f273bfb29e6855b246cd26d2f0a8bf898f8f7 100644 (file)
@@ -1,5 +1,11 @@
 Changes with Apache 1.3.30
 
+  *) SECURITY: CAN-2003-0993 (cve.mitre.org) 
+     Fix parsing of Allow/Deny rules using IP addresses without a
+     netmask; issue is only known to affect big-endian 64-bit
+     platforms; on affected platforms such rules would never produce
+     matches.  PR 23850.  [Henning Brauer <henning openbsd.org>]
+
   *) Fix mod_include's expression parser to recognize strings correctly
      even if they start with an escaped token.  [AndrĂ© Malo]
 
index 09d3db12763765d778c8057dca569aed34be7db3..1de9c32352d60b606445e77a5c56ff275612c110 100644 (file)
@@ -39,8 +39,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;
@@ -124,14 +124,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";
        }
@@ -143,24 +143,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 */
@@ -171,8 +173,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;
@@ -191,6 +193,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);
@@ -198,13 +201,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 = 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;
@@ -272,9 +275,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;