Merge branch 'master' of git://git.samba.org/samba
[samba.git] / source3 / lib / access.c
index 0d477116ed44b046b00cbd5c26611d12f36f098d..0b09e83ce35fb4dd83d3c2f2fc26eaa54cbcc888 100644 (file)
@@ -52,7 +52,7 @@ static bool masked_match(const char *tok, const char *slash, const char *s)
        SAFE_FREE(tok_copy);
 
         if (strlen(slash + 1) > 2) {
-               if (interpret_string_addr(&ss_mask, slash+1, 0)) {
+               if (!interpret_string_addr(&ss_mask, slash+1, 0)) {
                        return false;
                }
         } else {
@@ -66,7 +66,7 @@ static bool masked_match(const char *tok, const char *slash, const char *s)
                }
         }
 
-       return same_net(&ss_host, &ss_tok, &ss_mask);
+       return same_net((struct sockaddr *)&ss_host, (struct sockaddr *)&ss_tok, (struct sockaddr *)&ss_mask);
 }
 
 /* string_match - match string s against token tok */
@@ -97,13 +97,29 @@ static bool string_match(const char *tok,const char *s)
                }
        } else if (tok[0] == '@') { /* netgroup: look it up */
 #ifdef HAVE_NETGROUP
-               static char *mydomain = NULL;
+               DATA_BLOB tmp;
+               char *mydomain = NULL;
                char *hostname = NULL;
                bool netgroup_ok = false;
 
-               if (!mydomain)
+               if (memcache_lookup(
+                           NULL, SINGLETON_CACHE,
+                           data_blob_string_const_null("yp_default_domain"),
+                           &tmp)) {
+
+                       SMB_ASSERT(tmp.length > 0);
+                       mydomain = (tmp.data[0] == '\0')
+                               ? NULL : (char *)tmp.data;
+               }
+               else {
                        yp_get_default_domain(&mydomain);
 
+                       memcache_add(
+                               NULL, SINGLETON_CACHE,
+                               data_blob_string_const_null("yp_default_domain"),
+                               data_blob_string_const_null(mydomain?mydomain:""));
+               }
+
                if (!mydomain) {
                        DEBUG(0,("Unable to get default yp domain. "
                                "Try without it.\n"));
@@ -159,27 +175,43 @@ static bool string_match(const char *tok,const char *s)
 }
 
 /* client_match - match host name and address against token */
-static bool client_match(const char *tok, const void *item)
+bool client_match(const char *tok, const void *item)
 {
        const char **client = (const char **)item;
-       bool match = false;
 
        /*
         * Try to match the address first. If that fails, try to match the host
         * name if available.
         */
 
-       if ((match = string_match(tok, client[ADDR_INDEX])) == false) {
-               if (client[NAME_INDEX][0] != 0) {
-                       match = string_match(tok, client[NAME_INDEX]);
+       if (string_match(tok, client[ADDR_INDEX])) {
+               return true;
+       }
+
+       if (strnequal(client[ADDR_INDEX],"::ffff:",7) &&
+                       !strnequal(tok, "::ffff:",7)) {
+               /* client[ADDR_INDEX] is an IPv4 mapped to IPv6, but
+                * the list item is not. Try and match the IPv4 part of
+                * address only. This will happen a lot on IPv6 enabled
+                * systems with IPv4 allow/deny lists in smb.conf.
+                * Bug #5311. JRA.
+                */
+               if (string_match(tok, (client[ADDR_INDEX])+7)) {
+                       return true;
                }
        }
 
-       return match;
+       if (client[NAME_INDEX][0] != 0) {
+               if (string_match(tok, client[NAME_INDEX])) {
+                       return true;
+               }
+       }
+
+       return false;
 }
 
 /* list_match - match an item against a list of tokens with exceptions */
-static bool list_match(const char **list,const void *item,
+bool list_match(const char **list,const void *item,
                bool (*match_fn)(const char *, const void *))
 {
        bool match = false;
@@ -346,6 +378,8 @@ bool check_access(int sock, const char **allow_list, const char **deny_list)
                ret = true;
 
        if (!ret) {
+               char addr[INET6_ADDRSTRLEN];
+
                /* Bypass name resolution calls if the lists
                 * only contain IP addrs */
                if (only_ipaddrs_in_list(allow_list) &&
@@ -356,24 +390,24 @@ bool check_access(int sock, const char **allow_list, const char **deny_list)
                        ret = allow_access(deny_list,
                                        allow_list,
                                        "",
-                                       get_peer_addr(sock));
+                                       get_peer_addr(sock,addr,sizeof(addr)));
                } else {
                        DEBUG (3, ("check_access: hostnames in "
                                "host allow/deny list.\n"));
                        ret = allow_access(deny_list,
                                        allow_list,
                                        get_peer_name(sock,true),
-                                       get_peer_addr(sock));
+                                       get_peer_addr(sock,addr,sizeof(addr)));
                }
 
                if (ret) {
                        DEBUG(2,("Allowed connection from %s (%s)\n",
                                 only_ip ? "" : get_peer_name(sock,true),
-                                get_peer_addr(sock)));
+                                get_peer_addr(sock,addr,sizeof(addr))));
                } else {
                        DEBUG(0,("Denied connection from %s (%s)\n",
                                 only_ip ? "" : get_peer_name(sock,true),
-                                get_peer_addr(sock)));
+                                get_peer_addr(sock,addr,sizeof(addr))));
                }
        }