Sophie

Sophie

distrib > Mandriva > 10.0-com > i586 > by-pkgid > c3f48b97eea7ea342086686527f89d24 > files > 9

apache-1.3.29-1.4.100mdk.src.rpm

Security Fix (CAN-2003-0993, Apache PR 23850):
mod_access in Apache 1.3 before 1.3.30, when running big-endian 64-bit
platforms, does not properly parse Allow/Deny rules using IP addresses
without a netmask, which could allow remote attackers to bypass intended
access restrictions.

Index: src/modules/standard/mod_access.c
--- src/modules/standard/mod_access.c.orig	2003-02-03 18:13:27.000000000 +0100
+++ src/modules/standard/mod_access.c	2004-05-12 10:03:14.000000000 +0200
@@ -82,8 +82,8 @@
     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 @@
 
     }
     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 @@
 	}
 	/* 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 @@
 	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 @@
 		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 @@
 		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;
@@ -315,9 +318,9 @@
 	    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;