]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Created net_parse_range() from auth code.
authorTimo Sirainen <tss@iki.fi>
Sat, 21 Jun 2008 06:54:26 +0000 (09:54 +0300)
committerTimo Sirainen <tss@iki.fi>
Sat, 21 Jun 2008 06:54:26 +0000 (09:54 +0300)
--HG--
branch : HEAD

src/auth/auth-request.c
src/lib/network.c
src/lib/network.h

index 747fc2e5bbf0b977bf2e856af264d5b152cab357..efa2b5fd6b62e37f4ea67bce68d5d80c3d390e29 100644 (file)
@@ -868,38 +868,12 @@ bool auth_request_set_login_username(struct auth_request *request,
        return request->requested_login_user != NULL;
 }
 
-static int is_ip_in_network(const char *network, const struct ip_addr *ip)
-{
-       struct ip_addr src_ip, net_ip;
-       const char *p;
-       unsigned int max_bits, bits;
-
-       if (net_ipv6_mapped_ipv4_convert(ip, &src_ip) == 0)
-               ip = &src_ip;
-
-       max_bits = IPADDR_IS_V4(ip) ? 32 : 128;
-       p = strchr(network, '/');
-       if (p == NULL) {
-               /* full IP address must match */
-               bits = max_bits;
-       } else {
-               /* get the network mask */
-               network = t_strdup_until(network, p);
-               bits = strtoul(p+1, NULL, 10);
-               if (bits > max_bits)
-                       bits = max_bits;
-       }
-
-       if (net_addr2ip(network, &net_ip) < 0)
-               return -1;
-
-       return net_is_in_network(ip, &net_ip, bits);
-}
-
 static void auth_request_validate_networks(struct auth_request *request,
                                           const char *networks)
 {
        const char *const *net;
+       struct ip_addr net_ip;
+       unsigned int bits;
        bool found = FALSE;
 
        if (request->remote_ip.family == 0) {
@@ -913,15 +887,14 @@ static void auth_request_validate_networks(struct auth_request *request,
        for (net = t_strsplit_spaces(networks, ", "); *net != NULL; net++) {
                auth_request_log_debug(request, "auth",
                        "allow_nets: Matching for network %s", *net);
-               switch (is_ip_in_network(*net, &request->remote_ip)) {
-               case 1:
-                       found = TRUE;
-                       break;
-               case -1:
+
+               if (net_parse_range(*net, &net_ip, &bits) < 0) {
                        auth_request_log_info(request, "passdb",
                                "allow_nets: Invalid network '%s'", *net);
-                       break;
-               default:
+               }
+
+               if (net_is_in_network(&request->remote_ip, &net_ip, bits)) {
+                       found = TRUE;
                        break;
                }
        }
index 857f4d703cf462735a2318d511c6228e0677d2e7..33617e9a4951b89ea479fbe35efbc25064db250e 100644 (file)
@@ -5,6 +5,7 @@
 #include "fd-set-nonblock.h"
 #include "network.h"
 
+#include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <ctype.h>
@@ -704,13 +705,46 @@ bool is_ipv6_address(const char *addr)
        return TRUE;
 }
 
+int net_parse_range(const char *network, struct ip_addr *ip_r,
+                   unsigned int *bits_r)
+{
+       const char *p;
+       int bits, max_bits;
+
+       p = strchr(network, '/');
+       if (p != NULL)
+               network = t_strdup_until(network, p++);
+
+       if (net_addr2ip(network, ip_r) < 0)
+               return -1;
+
+       max_bits = IPADDR_IS_V4(ip_r) ? 32 : 128;
+       if (p == NULL) {
+               /* full IP address must match */
+               bits = max_bits;
+       } else {
+               /* get the network mask */
+               bits = atoi(p);
+               if (bits < 0 || bits > max_bits)
+                       return -1;
+       }
+       *bits_r = bits;
+       return 0;
+}
+
 bool net_is_in_network(const struct ip_addr *ip,
                       const struct ip_addr *net_ip, unsigned int bits)
 {
+       struct ip_addr tmp_ip;
        const uint32_t *ip1, *ip2;
        uint32_t mask, i1, i2;
        unsigned int pos, i;
 
+       if (net_ipv6_mapped_ipv4_convert(ip, &tmp_ip) == 0) {
+               /* IPv4 address mapped disguised as IPv6 address */
+               ip = &tmp_ip;
+       }
+
        if (IPADDR_IS_V4(ip) != IPADDR_IS_V4(net_ip)) {
                /* one is IPv6 and one is IPv4 */
                return FALSE;
index 5011443be7bca6f6adf6ed10abd20359196ad1d9..a72a685a50d9f92f6a6b0f11bdd9d66051f357b9 100644 (file)
@@ -110,7 +110,11 @@ const char *net_getservbyport(unsigned short port) ATTR_CONST;
 bool is_ipv4_address(const char *addr) ATTR_PURE;
 bool is_ipv6_address(const char *addr) ATTR_PURE;
 
-/* Returns TRUE if ip is in net_ip/bits network. */
+/* Parse network as ip/bits. Returns 0 if successful, -1 if invalid input. */
+int net_parse_range(const char *network, struct ip_addr *ip_r,
+                   unsigned int *bits_r);
+/* Returns TRUE if ip is in net_ip/bits network. IPv6 mapped IPv4 addresses
+   are converted to plain IPv4 addresses before matching. */
 bool net_is_in_network(const struct ip_addr *ip, const struct ip_addr *net_ip,
                       unsigned int bits) ATTR_PURE;