[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