Sophie

Sophie

distrib > Mandriva > 2007.0 > i586 > by-pkgid > 8ccb93f8217ebb055dff98778b0b9f34 > files > 15

proftpd-1.3.0-4.6mdv2007.0.src.rpm

Index: modules/mod_core.c
===================================================================
RCS file: /cvsroot/proftp/proftpd/modules/mod_core.c,v
retrieving revision 1.277
diff -u -r1.277 mod_core.c
--- modules/mod_core.c	21 Feb 2006 06:55:38 -0000	1.277
+++ modules/mod_core.c	11 May 2006 18:58:43 -0000
@@ -1025,10 +1025,15 @@
     if (strcasecmp("all", *(cargv + 1)) == 0 ||
         strcasecmp("none", *(cargv + 1)) == 0) {
       pr_netacl_t *acl = pr_netacl_create(cmd->tmp_pool, *(cargv + 1));
+      if (!acl) {
+        CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "bad ACL definition '",
+          *(cargv + 1), "': ", strerror(errno), NULL));
+      }
 
-      if (pr_class_add_acl(acl) < 0)
+      if (pr_class_add_acl(acl) < 0) {
         CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "error adding rule '",
           *(cargv + 1), "': ", strerror(errno), NULL));
+      }
 
       cargc = 0;
     }
@@ -1043,18 +1048,24 @@
 
     while ((ent = get_token(&str, ",")) != NULL) {
       if (*ent) {
-       pr_netacl_t *acl;
+        pr_netacl_t *acl;
 
-       if (strcasecmp(ent, "all") == 0 ||
-           strcasecmp(ent, "none") == 0) {
-          cargc = 0;
-          break;
+        if (strcasecmp(ent, "all") == 0 ||
+            strcasecmp(ent, "none") == 0) {
+           cargc = 0;
+           break;
+         }
+
+        acl = pr_netacl_create(cmd->tmp_pool, ent);
+        if (!acl) {
+          CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "bad ACL definition '",
+            *(cargv + 1), "': ", strerror(errno), NULL));
         }
 
-       acl = pr_netacl_create(cmd->tmp_pool, ent);
-       if (pr_class_add_acl(acl) < 0)
-         CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "error adding rule '", ent,
-           "': ", strerror(errno), NULL));
+        if (pr_class_add_acl(acl) < 0) {
+          CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "error adding rule '", ent,
+            "': ", strerror(errno), NULL));
+        }
       }
     }
   }
@@ -2511,9 +2522,10 @@
         }
 
         acl = pr_netacl_create(c->pool, ent);
-        if (!acl)
-          CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "bad ACL definition: '",
+        if (!acl) {
+          CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "bad ACL definition '",
             ent, "': ", strerror(errno), NULL));     
+        }
 
         *((pr_netacl_t **) push_array(list)) = acl;
       }
Index: src/netacl.c
===================================================================
RCS file: /cvsroot/proftp/proftpd/src/netacl.c,v
retrieving revision 1.10
diff -u -r1.10 netacl.c
--- src/netacl.c	10 Oct 2005 17:58:31 -0000	1.10
+++ src/netacl.c	11 May 2006 18:58:43 -0000
@@ -1,6 +1,6 @@
 /*
  * ProFTPD - FTP server daemon
- * Copyright (c) 2003 The ProFTPD Project team
+ * Copyright (c) 2003-2006 The ProFTPD Project team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -172,15 +172,20 @@
 
 #ifdef PR_USE_IPV6
       case AF_INET6: {
-        /* Make sure that the given number of bits is not more than supported
-         * for IPv6 addresses (128).
-         */
         if (acl->masklen > 128) {
-          errno = EINVAL;
-          return NULL;
-        }
+           errno = EINVAL;
+           return NULL;
 
-        break;
+        } else if (pr_netaddr_is_v4mappedv6(acl->addr) == TRUE &&
+                   acl->masklen > 32) {
+
+          /* The admin may be trying to use IPv6-style masks on IPv4-mapped
+           * IPv6 addresses, which of course will not work as expected. 
+           * If the mask is 32 bits or more, warn the admin.
+           */
+          pr_log_pri(PR_LOG_WARNING, "warning: possibly using IPv6-style netmask on IPv4-mapped IPv6 address, which will not work as expected");
+          break;
+        }
       }
 #endif /* PR_USE_IPV6 */
 
Index: src/netaddr.c
===================================================================
RCS file: /cvsroot/proftp/proftpd/src/netaddr.c,v
retrieving revision 1.51
diff -u -r1.51 netaddr.c
--- src/netaddr.c	19 Sep 2005 21:35:38 -0000	1.51
+++ src/netaddr.c	11 May 2006 18:58:43 -0000
@@ -1,6 +1,6 @@
 /*
  * ProFTPD - FTP server daemon
- * Copyright (c) 2003-2005 The ProFTPD Project team
+ * Copyright (c) 2003-2006 The ProFTPD Project team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -219,8 +219,7 @@
 }
 #endif /* !HAVE_INET_PTON */
 
-#ifdef HAVE_GETHOSTBYNAME2
-static void *get_v4inaddr(pr_netaddr_t *na) {
+static void *get_v4inaddr(const pr_netaddr_t *na) {
 
   /* This function is specifically for IPv4 clients (when gethostbyname2(2) is
    * present) that have an IPv4-mapped IPv6 address, when performing reverse
@@ -234,7 +233,6 @@
 
   return (((char *) pr_netaddr_get_inaddr(na)) + 12);
 }
-#endif /* HAVE_GETHOSTBYNAME2 */
 
 int pr_netaddr_set_reverse_dns(int enable) {
   int old_enable = reverse_dns;
@@ -652,6 +650,10 @@
 }
 
 int pr_netaddr_cmp(const pr_netaddr_t *na1, const pr_netaddr_t *na2) {
+  pool *tmp_pool = NULL;
+  pr_netaddr_t *a, *b;
+  int res;
+
   if (na1 && !na2)
     return 1;
 
@@ -662,29 +664,85 @@
     return 0;
 
   if (pr_netaddr_get_family(na1) != pr_netaddr_get_family(na2)) {
-    /* Cannot compare addresses from different families. */
-    errno = EINVAL;
-    return -1;
+
+    /* Cannot compare addresses from different families, unless one
+     * of the netaddrs has an AF_INET family, and the other has an
+     * AF_INET6 family AND is an IPv4-mapped IPv6 address.
+     */
+
+    if (pr_netaddr_is_v4mappedv6(na1) != TRUE &&
+        pr_netaddr_is_v4mappedv6(na2) != TRUE) {
+      errno = EINVAL;
+      return -1;
+    }
+
+    if (pr_netaddr_is_v4mappedv6(na1) == TRUE) {
+      tmp_pool = make_sub_pool(permanent_pool);
+
+      /* This case means that na1 is an IPv4-mapped IPv6 address, and
+       * na2 is an IPv4 address.
+       */
+      a = pr_netaddr_alloc(tmp_pool);
+      pr_netaddr_set_family(a, AF_INET);
+      pr_netaddr_set_port(a, pr_netaddr_get_port(na1));
+      memcpy(&a->na_addr.v4.sin_addr, get_v4inaddr(na1),
+        sizeof(struct in_addr));
+
+      b = (pr_netaddr_t *) na2;
+
+    } else if (pr_netaddr_is_v4mappedv6(na2) == TRUE) {
+      tmp_pool = make_sub_pool(permanent_pool);
+
+      /* This case means that na is an IPv4 address, and na2 is an
+       * IPv4-mapped IPv6 address.
+       */
+      a = (pr_netaddr_t *) na1;
+
+      b = pr_netaddr_alloc(tmp_pool);
+      pr_netaddr_set_family(b, AF_INET);
+      pr_netaddr_set_port(b, pr_netaddr_get_port(na2));
+      memcpy(&b->na_addr.v4.sin_addr, get_v4inaddr(na2),
+        sizeof(struct in_addr));
+
+    } else {
+      a = (pr_netaddr_t *) na1;
+      b = (pr_netaddr_t *) na2;
+    }
+
+  } else {
+    a = (pr_netaddr_t *) na1;
+    b = (pr_netaddr_t *) na2;
   }
 
-  switch (pr_netaddr_get_family(na1)) {
+  switch (pr_netaddr_get_family(a)) {
     case AF_INET:
-      return memcmp(&na1->na_addr.v4.sin_addr, &na2->na_addr.v4.sin_addr,
+      res = memcmp(&a->na_addr.v4.sin_addr, &b->na_addr.v4.sin_addr,
         sizeof(struct in_addr));
+      if (tmp_pool)
+        destroy_pool(tmp_pool);
+      return res;
 
 #ifdef PR_USE_IPV6
     case AF_INET6:
-      return memcmp(&na1->na_addr.v6.sin6_addr, &na2->na_addr.v6.sin6_addr,
+      res = memcmp(&a->na_addr.v6.sin6_addr, &b->na_addr.v6.sin6_addr,
         sizeof(struct in6_addr));
+      if (tmp_pool);
+        destroy_pool(tmp_pool);
+      return res;
 #endif /* PR_USE_IPV6 */
   }
 
+  if (tmp_pool)
+    destroy_pool(tmp_pool);
+
   errno = EPERM;
   return -1;
 }
 
 int pr_netaddr_ncmp(const pr_netaddr_t *na1, const pr_netaddr_t *na2,
     unsigned int bitlen) {
+  pool *tmp_pool = NULL;
+  pr_netaddr_t *a, *b;
   unsigned int nbytes, nbits;
   const unsigned char *in1, *in2;
 
@@ -698,12 +756,57 @@
     return 0;
 
   if (pr_netaddr_get_family(na1) != pr_netaddr_get_family(na2)) {
-    /* Cannot compare addresses from different families. */
-    errno = EINVAL;
-    return -1;
+
+    /* Cannot compare addresses from different families, unless one
+     * of the netaddrs has an AF_INET family, and the other has an
+     * AF_INET6 family AND is an IPv4-mapped IPv6 address.
+     */
+
+    if (pr_netaddr_is_v4mappedv6(na1) != TRUE &&
+        pr_netaddr_is_v4mappedv6(na2) != TRUE) {
+      errno = EINVAL;
+      return -1;
+    }
+
+    if (pr_netaddr_is_v4mappedv6(na1) == TRUE) {
+      tmp_pool = make_sub_pool(permanent_pool);
+
+      /* This case means that na1 is an IPv4-mapped IPv6 address, and
+       * na2 is an IPv4 address.
+       */
+      a = pr_netaddr_alloc(tmp_pool);
+      pr_netaddr_set_family(a, AF_INET);
+      pr_netaddr_set_port(a, pr_netaddr_get_port(na1));
+      memcpy(&a->na_addr.v4.sin_addr, get_v4inaddr(na1),
+        sizeof(struct in_addr));
+
+      b = (pr_netaddr_t *) na2;
+
+    } else if (pr_netaddr_is_v4mappedv6(na2) == TRUE) {
+      tmp_pool = make_sub_pool(permanent_pool);
+
+      /* This case means that na is an IPv4 address, and na2 is an
+       * IPv4-mapped IPv6 address.
+       */
+      a = (pr_netaddr_t *) na1;
+
+      b = pr_netaddr_alloc(tmp_pool);
+      pr_netaddr_set_family(b, AF_INET);
+      pr_netaddr_set_port(b, pr_netaddr_get_port(na2));
+      memcpy(&b->na_addr.v4.sin_addr, get_v4inaddr(na2),
+        sizeof(struct in_addr));
+
+    } else {
+      a = (pr_netaddr_t *) na1;
+      b = (pr_netaddr_t *) na2;
+    }
+
+  } else {
+    a = (pr_netaddr_t *) na1;
+    b = (pr_netaddr_t *) na2;
   }
 
-  switch (pr_netaddr_get_family(na1)) {
+  switch (pr_netaddr_get_family(a)) {
     case AF_INET: {
       /* Make sure that the given number of bits is not more than supported
        * for IPv4 addresses (32).
@@ -736,8 +839,8 @@
   }
 
   /* Retrieve pointers to the contained in_addrs. */
-  in1 = (const unsigned char *) pr_netaddr_get_inaddr(na1);
-  in2 = (const unsigned char *) pr_netaddr_get_inaddr(na2);
+  in1 = (const unsigned char *) pr_netaddr_get_inaddr(a);
+  in2 = (const unsigned char *) pr_netaddr_get_inaddr(b);
 
   /* Determine the number of bytes, and leftover bits, in the given
    * bit length.
@@ -750,8 +853,12 @@
     int res = memcmp(in1, in2, nbytes);
 
     /* No need to continue comparing the addresses if they differ already. */
-    if (res != 0)
+    if (res != 0) {
+      if (tmp_pool)
+        destroy_pool(tmp_pool);
+
       return res;
+    }
   }
 
   /* Next, compare the remaining bits in the addresses. */
@@ -765,13 +872,22 @@
     /* Build up a mask covering the bits left to be checked. */
     mask = (0xff << (8 - nbits)) & 0xff;
 
-    if ((in1byte & mask) > (in2byte & mask))
+    if ((in1byte & mask) > (in2byte & mask)) {
+      if (tmp_pool)
+        destroy_pool(tmp_pool);
       return 1;
+    }
 
-    if ((in1byte & mask) < (in2byte & mask))
+    if ((in1byte & mask) < (in2byte & mask)) {
+      if (tmp_pool)
+        destroy_pool(tmp_pool);
       return -1;
+    }
   }
 
+  if (tmp_pool)
+    destroy_pool(tmp_pool);
+
   /* If we've made it this far, the addresses match, for the given bit
    * length.
    */