[PATCH] Update masked_match in source4 to support IPv6 addresses (resend)

Heath Kehoe heath at digitalartefacts.com
Thu Nov 10 19:02:30 UTC 2016


We have an AD environment backed entirely by Samba4. We have a
remote location where I spun up a Samba4 instance and made it a DC.
The remote subnet is connected to our "main" subnet via VPN, with
both IPv4 and IPv6.

I set up an AD Site for the remote location and assigned the
appropriate subnets (both v4 and v6) to it. However, a Windows
client at the remote location never associated with the correct site,
in that 'nltest /dsgetsite' always returned the default site. Also,
that client would sometimes use a DC at the main site; and worse,
clients at the main site sometimes bound to the DC at the remote
site's DC causing long login times.

So I tracked down what Samba was doing to match a client to a site.
I found samdb_client_site_name() which in turn uses
socket_allow_access() which led to masked_match() in
source4/lib/socket/access.c that clearly only worked with IPv4
addresses. Since we are using IPv6, clients failed to be matched
to any site.

So I ported the masked_match() that appears in source3 (which had
already been updated to support IPv6) over to source4, which resolves
(for us) the problem with sites.

Couple of notes

  * I didn't copy all of the 'if' noise that's in front of the
    masked_match invocation in source3/lib/access.c to the
    corresponding invocation in source4/lib/socket/access.c, because
    the first thing masked_match does is call interpret_string_addr
    which itself will validate the input.

  * I had to add 'netif' to deps in source4/lib/socket/wscript_build
    to get make_netmask()

-------------- next part --------------
>From 6fa1e442e14d231b31f700304cd1b2e94ef2e5a5 Mon Sep 17 00:00:00 2001
From: Heath Kehoe <heath at digitalartefacts.com>
Date: Thu, 10 Nov 2016 11:33:49 -0600
Subject: [PATCH] Update masked_match in source4 to support IPv6

Port masked_match from source3/lib/access.c to source4/lib/socket/access.c in order to add support for IPv6 addresses.

Signed-off-by: Heath Kehoe <heath at digitalartefacts.com>
---
 source4/lib/socket/access.c      | 76 ++++++++++++++++++++++++++--------------
 source4/lib/socket/wscript_build |  2 +-
 2 files changed, 51 insertions(+), 27 deletions(-)

diff --git a/source4/lib/socket/access.c b/source4/lib/socket/access.c
index adc8105..2328ec1 100644
--- a/source4/lib/socket/access.c
+++ b/source4/lib/socket/access.c
@@ -32,43 +32,67 @@
 
 #include "includes.h"
 #include "system/network.h"
+#include "lib/socket/interfaces.h"
 #include "lib/socket/socket.h"
 #include "system/locale.h"
 #include "lib/util/util_net.h"
 
 #define	FAIL		(-1)
-#define ALLONES  ((uint32_t)0xFFFFFFFF)
 
 /* masked_match - match address against netnumber/netmask */
 static bool masked_match(TALLOC_CTX *mem_ctx, const char *tok, const char *slash, const char *s)
 {
-	uint32_t net;
-	uint32_t mask;
-	uint32_t addr;
-	char *tok_cpy;
+	struct sockaddr_storage ss_mask;
+	struct sockaddr_storage ss_tok;
+	struct sockaddr_storage ss_host;
+	char *tok_copy = NULL;
 
-	if ((addr = interpret_addr(s)) == INADDR_NONE)
-		return false;
-
-	tok_cpy = talloc_strdup(mem_ctx, tok);
-	tok_cpy[PTR_DIFF(slash,tok)] = '\0';
-	net = interpret_addr(tok_cpy);
-	talloc_free(tok_cpy);
-
-        if (strlen(slash + 1) > 2) {
-                mask = interpret_addr(slash + 1);
-        } else {
-		mask = (uint32_t)((ALLONES >> atoi(slash + 1)) ^ ALLONES);
-		/* convert to network byte order */
-		mask = htonl(mask);
-        }
-
-	if (net == INADDR_NONE || mask == INADDR_NONE) {
-		DEBUG(0,("access: bad net/mask access control: %s\n", tok));
+	if (!interpret_string_addr(&ss_host, s, 0)) {
 		return false;
 	}
-	
-	return (addr & mask) == (net & mask);
+
+	if (*tok == '[') {
+		/* IPv6 address - remove braces. */
+		tok_copy = talloc_strdup(mem_ctx, tok+1);
+		if (!tok_copy) {
+			return false;
+		}
+		/* Remove the terminating ']' */
+		tok_copy[PTR_DIFF(slash,tok)-1] = '\0';
+	} else {
+		tok_copy = talloc_strdup(mem_ctx, tok);
+		if (!tok_copy) {
+			return false;
+		}
+		/* Remove the terminating '/' */
+		tok_copy[PTR_DIFF(slash,tok)] = '\0';
+	}
+
+	if (!interpret_string_addr(&ss_tok, tok_copy, 0)) {
+		talloc_free(tok_copy);
+		return false;
+	}
+
+	talloc_free(tok_copy);
+
+	if (strlen(slash + 1) > 2) {
+		if (!interpret_string_addr(&ss_mask, slash+1, 0)) {
+			return false;
+		}
+	} else {
+		char *endp = NULL;
+		unsigned long val = strtoul(slash+1, &endp, 0);
+		if (slash+1 == endp || (endp && *endp != '\0')) {
+			return false;
+		}
+		if (!make_netmask(&ss_mask, &ss_tok, val)) {
+			return false;
+		}
+	}
+
+	return same_net((struct sockaddr *)(void *)&ss_host,
+			(struct sockaddr *)(void *)&ss_tok,
+			(struct sockaddr *)(void *)&ss_mask);
 }
 
 /* string_match - match string against token */
@@ -116,7 +140,7 @@ static bool string_match(TALLOC_CTX *mem_ctx, const char *tok,const char *s, cha
 		if (strncmp(tok, s, tok_len) == 0)
 			return true;
 	} else if ((cut = strchr(tok, '/')) != 0) {	/* netnumber/netmask */
-		if (isdigit((int)s[0]) && masked_match(mem_ctx, tok, cut, s))
+		if (masked_match(mem_ctx, tok, cut, s))
 			return true;
 	} else if (strchr(tok, '*') != 0) {
 		*invalid_char = '*';
diff --git a/source4/lib/socket/wscript_build b/source4/lib/socket/wscript_build
index 1cb89c6..225e605 100644
--- a/source4/lib/socket/wscript_build
+++ b/source4/lib/socket/wscript_build
@@ -24,6 +24,6 @@ bld.SAMBA_MODULE('socket_unix',
 bld.SAMBA_SUBSYSTEM('samba_socket',
     source='socket.c access.c connect_multi.c connect.c',
     public_deps='talloc LIBTSOCKET',
-    deps='cli_composite LIBCLI_RESOLVE socket_ip socket_unix'
+    deps='cli_composite LIBCLI_RESOLVE socket_ip socket_unix netif'
     )
 
-- 
2.10.2



More information about the samba-technical mailing list