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

Jeremy Allison jra at samba.org
Fri Nov 11 05:05:43 UTC 2016


On Thu, Nov 10, 2016 at 02:09:25PM -0600, Heath Kehoe wrote:
> On 11/10/16 13:09, Jeremy Allison wrote:
> >On Thu, Nov 10, 2016 at 01:02:30PM -0600, Heath Kehoe wrote:
> >>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.
> >Oh good catch. I think the correct fix for this is to
> >move the source3/ masked match to lib/util/access.c
> >and make both source3 and source4 link against it though.
> >
> >If I create this patch can you test it for me ?
> >
> >Jeremy.
> >
> 
> I can.

Can you try this patchset for me ? Compiles but I haven't
tried it with make test yet (will do so tomorrow, it's late
here).

This unifies the access check function between the source3
and source4 directories and moves it to lib/util instead.

I logged a bug to track this:

https://bugzilla.samba.org/show_bug.cgi?id=12419

Cheers,

	Jeremy.
-------------- next part --------------
>From cc1e95a6306dc59e1c3c7e4cb69f1d65b9a6595f Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 10 Nov 2016 16:27:56 -0800
Subject: [PATCH 1/6] lib/util: Move unix_wild_match() from source3/lib/util to
 lib/util/

Use top-level functions instead of source3 specific ones.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12419

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 lib/util/unix_match.c   | 183 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/util/unix_match.h   |  25 +++++++
 lib/util/wscript_build  |   2 +-
 source3/include/proto.h |   2 +-
 source3/lib/util.c      | 146 --------------------------------------
 5 files changed, 210 insertions(+), 148 deletions(-)
 create mode 100644 lib/util/unix_match.c
 create mode 100644 lib/util/unix_match.h

diff --git a/lib/util/unix_match.c b/lib/util/unix_match.c
new file mode 100644
index 0000000..38edc18
--- /dev/null
+++ b/lib/util/unix_match.c
@@ -0,0 +1,183 @@
+/*
+   Unix SMB/CIFS implementation.
+   Samba utility functions
+   Copyright (C) Jeremy Allison       2001
+
+   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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include <talloc.h>
+#include "lib/util/talloc_stack.h"
+#include "lib/util/charset/charset.h"
+#include "lib/util/unix_match.h"
+
+/*********************************************************
+ Recursive routine that is called by unix_wild_match.
+*********************************************************/
+
+static bool unix_do_match(const char *regexp, const char *str)
+{
+	const char *p;
+
+	for( p = regexp; *p && *str; ) {
+
+		switch(*p) {
+			case '?':
+				str++;
+				p++;
+				break;
+
+			case '*':
+
+				/*
+				 * Look for a character matching
+				 * the one after the '*'.
+				 */
+				p++;
+				if(!*p) {
+					return true; /* Automatic match */
+				}
+				while(*str) {
+
+					while(*str && (*p != *str)) {
+						str++;
+					}
+
+					/*
+					 * Patch from weidel at multichart.de.
+					 * In the case of the regexp
+					 * '*XX*' we want to ensure there are
+					 * at least 2 'X' characters in the
+					 * string after the '*' for a match to
+					 * be made.
+					 */
+
+					{
+						int matchcount=0;
+
+						/*
+						 * Eat all the characters that
+						 * match, but count how many
+						 * there were.
+						 */
+
+						while(*str && (*p == *str)) {
+							str++;
+							matchcount++;
+						}
+
+						/*
+						 * Now check that if the regexp
+						 * had n identical characters
+						 * that matchcount had at least
+						 * that many matches.
+						 */
+
+						while (*(p+1) && (*(p+1)==*p)) {
+							p++;
+							matchcount--;
+						}
+
+						if ( matchcount <= 0 ) {
+							return false;
+						}
+					}
+
+					/*
+					 * We've eaten the match char
+					 * after the '*'
+					 */
+					str--;
+
+					if(unix_do_match(p, str)) {
+						return true;
+					}
+
+					if(!*str) {
+						return false;
+					} else {
+						str++;
+					}
+				}
+				return false;
+
+			default:
+				if(*str != *p) {
+					return false;
+				}
+				str++;
+				p++;
+				break;
+		}
+	}
+
+	if(!*p && !*str) {
+		return true;
+	}
+
+	if (!*p && str[0] == '.' && str[1] == 0) {
+		return true;
+	}
+
+	if (!*str && *p == '?') {
+		while (*p == '?') {
+			p++;
+		}
+		return(!*p);
+	}
+
+	if(!*str && (*p == '*' && p[1] == '\0')) {
+		return true;
+	}
+
+	return false;
+}
+
+/*******************************************************************
+ Simple case insensitive interface to a UNIX wildcard matcher.
+ Returns True if match, False if not.
+*******************************************************************/
+
+bool unix_wild_match(const char *pattern, const char *string)
+{
+	TALLOC_CTX *ctx = talloc_stackframe();
+	char *p2;
+	char *s2;
+	char *p;
+	bool ret = false;
+
+	p2 = strlower_talloc(ctx, pattern);
+	s2 = strlower_talloc(ctx, string);
+	if (!p2 || !s2) {
+		TALLOC_FREE(ctx);
+		return false;
+	}
+
+	/* Remove any *? and ** from the pattern as they are meaningless */
+	for(p = p2; *p; p++) {
+		while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
+			memmove(&p[1], &p[2], strlen(&p[2])+1);
+		}
+	}
+
+	if (p2[0] == '*' && p2[1] == '\0') {
+		TALLOC_FREE(ctx);
+		return true;
+	}
+
+	ret = unix_do_match(p2, s2);
+	TALLOC_FREE(ctx);
+	return ret;
+}
diff --git a/lib/util/unix_match.h b/lib/util/unix_match.h
new file mode 100644
index 0000000..a7b6935
--- /dev/null
+++ b/lib/util/unix_match.h
@@ -0,0 +1,25 @@
+/*
+   Unix SMB/CIFS implementation.
+   Utility functions for Samba
+   Copyright (C) Jeremy Allison 2001
+
+   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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _UNIX_MASK_H_
+#define _UNIX_MASK_H_
+
+bool unix_wild_match(const char *pattern, const char *string);
+
+#endif
diff --git a/lib/util/wscript_build b/lib/util/wscript_build
index 6d2ab4a..e2ae411 100755
--- a/lib/util/wscript_build
+++ b/lib/util/wscript_build
@@ -120,7 +120,7 @@ else:
                     idtree_random.c base64.c
                     util_str.c util_str_common.c ms_fnmatch.c
                     server_id.c dprintf.c bitmap.c pidfile.c
-                    tevent_debug.c memcache.c''',
+                    tevent_debug.c memcache.c unix_match.c''',
                   deps='samba-util-core DYNCONFIG close-low-fd tini tiniparser genrand',
                   public_deps='talloc tevent execinfo pthread LIBCRYPTO charset util_setid systemd systemd-daemon',
                   public_headers='debug.h attr.h byteorder.h data_blob.h memory.h safe_string.h time.h talloc_stack.h xfile.h string_wrappers.h idtree.h idtree_random.h blocking.h signal.h substitute.h fault.h genrand.h',
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 0b0a2b5..2758dc5 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -411,7 +411,7 @@ bool ms_has_wild_w(const smb_ucs2_t *s);
 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive);
 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive);
 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive);
-bool unix_wild_match(const char *pattern, const char *string);
+#include "lib/util/unix_match.h"
 bool name_to_fqdn(fstring fqdn, const char *name);
 uint32_t map_share_mode_to_deny_mode(uint32_t share_access, uint32_t private_options);
 
diff --git a/source3/lib/util.c b/source3/lib/util.c
index bab3998..85cb9b3 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -1785,152 +1785,6 @@ bool mask_match_list(const char *string, char **list, int listLen, bool is_case_
        return False;
 }
 
-/*********************************************************
- Recursive routine that is called by unix_wild_match.
-*********************************************************/
-
-static bool unix_do_match(const char *regexp, const char *str)
-{
-	const char *p;
-
-	for( p = regexp; *p && *str; ) {
-
-		switch(*p) {
-			case '?':
-				str++;
-				p++;
-				break;
-
-			case '*':
-
-				/*
-				 * Look for a character matching 
-				 * the one after the '*'.
-				 */
-				p++;
-				if(!*p)
-					return true; /* Automatic match */
-				while(*str) {
-
-					while(*str && (*p != *str))
-						str++;
-
-					/*
-					 * Patch from weidel at multichart.de. In the case of the regexp
-					 * '*XX*' we want to ensure there are at least 2 'X' characters
-					 * in the string after the '*' for a match to be made.
-					 */
-
-					{
-						int matchcount=0;
-
-						/*
-						 * Eat all the characters that match, but count how many there were.
-						 */
-
-						while(*str && (*p == *str)) {
-							str++;
-							matchcount++;
-						}
-
-						/*
-						 * Now check that if the regexp had n identical characters that
-						 * matchcount had at least that many matches.
-						 */
-
-						while ( *(p+1) && (*(p+1) == *p)) {
-							p++;
-							matchcount--;
-						}
-
-						if ( matchcount <= 0 )
-							return false;
-					}
-
-					str--; /* We've eaten the match char after the '*' */
-
-					if(unix_do_match(p, str))
-						return true;
-
-					if(!*str)
-						return false;
-					else
-						str++;
-				}
-				return false;
-
-			default:
-				if(*str != *p)
-					return false;
-				str++;
-				p++;
-				break;
-		}
-	}
-
-	if(!*p && !*str)
-		return true;
-
-	if (!*p && str[0] == '.' && str[1] == 0)
-		return true;
-
-	if (!*str && *p == '?') {
-		while (*p == '?')
-			p++;
-		return(!*p);
-	}
-
-	if(!*str && (*p == '*' && p[1] == '\0'))
-		return true;
-
-	return false;
-}
-
-/*******************************************************************
- Simple case insensitive interface to a UNIX wildcard matcher.
- Returns True if match, False if not.
-*******************************************************************/
-
-bool unix_wild_match(const char *pattern, const char *string)
-{
-	TALLOC_CTX *ctx = talloc_stackframe();
-	char *p2;
-	char *s2;
-	char *p;
-	bool ret = false;
-
-	p2 = talloc_strdup(ctx,pattern);
-	s2 = talloc_strdup(ctx,string);
-	if (!p2 || !s2) {
-		TALLOC_FREE(ctx);
-		return false;
-	}
-	if (!strlower_m(p2)) {
-		TALLOC_FREE(ctx);
-		return false;
-	}
-	if (!strlower_m(s2)) {
-		TALLOC_FREE(ctx);
-		return false;
-	}
-
-	/* Remove any *? and ** from the pattern as they are meaningless */
-	for(p = p2; *p; p++) {
-		while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
-			memmove(&p[1], &p[2], strlen(&p[2])+1);
-		}
-	}
-
-	if (strequal(p2,"*")) {
-		TALLOC_FREE(ctx);
-		return true;
-	}
-
-	ret = unix_do_match(p2, s2);
-	TALLOC_FREE(ctx);
-	return ret;
-}
-
 /**********************************************************************
   Converts a name to a fully qualified domain name.
   Returns true if lookup succeeded, false if not (then fqdn is set to name)
-- 
2.7.4


>From 21b6ab29b62522183b5f28afa7c82803e63d800d Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 10 Nov 2016 17:02:08 -0800
Subject: [PATCH 2/6] source3/lib/access.c: Change from SMB_STRDUP macro to
 underlying smb_xstrdup function.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12419

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/lib/access.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/source3/lib/access.c b/source3/lib/access.c
index ad868fa..49c4f8e 100644
--- a/source3/lib/access.c
+++ b/source3/lib/access.c
@@ -13,6 +13,7 @@
 #include "includes.h"
 #include "../lib/util/memcache.h"
 #include "lib/socket/interfaces.h"
+#include "lib/util/samba_util.h"
 
 #define NAME_INDEX 0
 #define ADDR_INDEX 1
@@ -31,14 +32,14 @@ static bool masked_match(const char *tok, const char *slash, const char *s)
 
 	if (*tok == '[') {
 		/* IPv6 address - remove braces. */
-		tok_copy = SMB_STRDUP(tok+1);
+		tok_copy = smb_xstrdup(tok+1);
 		if (!tok_copy) {
 			return false;
 		}
 		/* Remove the terminating ']' */
 		tok_copy[PTR_DIFF(slash,tok)-1] = '\0';
 	} else {
-		tok_copy = SMB_STRDUP(tok);
+		tok_copy = smb_xstrdup(tok);
 		if (!tok_copy) {
 			return false;
 		}
@@ -128,7 +129,7 @@ static bool string_match(const char *tok,const char *s)
 			DEBUG(0,("Unable to get default yp domain. "
 				"Try without it.\n"));
 		}
-		if (!(hostname = SMB_STRDUP(s))) {
+		if (!(hostname = smb_xstrdup(s))) {
 			DEBUG(1,("out of memory for strdup!\n"));
 			return false;
 		}
-- 
2.7.4


>From c9406540a3c3f7a99f642b1f71b131194fc81bb4 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 10 Nov 2016 17:07:11 -0800
Subject: [PATCH 3/6] source3/lib/access.c: Use top level function strequal_m
 not the s3 strequal

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12419

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/lib/access.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/source3/lib/access.c b/source3/lib/access.c
index 49c4f8e..2875b03 100644
--- a/source3/lib/access.c
+++ b/source3/lib/access.c
@@ -97,7 +97,7 @@ static bool string_match(const char *tok,const char *s)
 
 	if (tok[0] == '.') {			/* domain: match last fields */
 		if ((str_len = strlen(s)) > (tok_len = strlen(tok))
-		    && strequal(tok, s + str_len - tok_len)) {
+		    && strequal_m(tok, s + str_len - tok_len)) {
 			return true;
 		}
 	} else if (tok[0] == '@') { /* netgroup: look it up */
@@ -150,15 +150,15 @@ static bool string_match(const char *tok,const char *s)
 		DEBUG(0,("access: netgroup support is not configured\n"));
 		return false;
 #endif
-	} else if (strequal(tok, "ALL")) {	/* all: match any */
+	} else if (strequal_m(tok, "ALL")) {	/* all: match any */
 		return true;
-	} else if (strequal(tok, "FAIL")) {	/* fail: match any */
+	} else if (strequal_m(tok, "FAIL")) {	/* fail: match any */
 		return true;
-	} else if (strequal(tok, "LOCAL")) {	/* local: no dots */
-		if (strchr_m(s, '.') == 0 && !strequal(s, "unknown")) {
+	} else if (strequal_m(tok, "LOCAL")) {	/* local: no dots */
+		if (strchr_m(s, '.') == 0 && !strequal_m(s, "unknown")) {
 			return true;
 		}
-	} else if (strequal(tok, s)) {   /* match host name or address */
+	} else if (strequal_m(tok, s)) {   /* match host name or address */
 		return true;
 	} else if (tok[(tok_len = strlen(tok)) - 1] == '.') {	/* network */
 		if (strncmp(tok, s, tok_len) == 0) {
@@ -236,7 +236,7 @@ bool list_match(const char **list,const void *item,
 	 */
 
 	for (; *list ; list++) {
-		if (strequal(*list, "EXCEPT")) {
+		if (strequal_m(*list, "EXCEPT")) {
 			/* EXCEPT: give up */
 			break;
 		}
@@ -248,7 +248,7 @@ bool list_match(const char **list,const void *item,
 	/* Process exceptions to true or FAIL matches. */
 
 	if (match != false) {
-		while (*list  && !strequal(*list, "EXCEPT")) {
+		while (*list  && !strequal_m(*list, "EXCEPT")) {
 			list++;
 		}
 
-- 
2.7.4


>From 71f5c6d6941b66119a3568e5ff3df134317ccb68 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 10 Nov 2016 17:09:33 -0800
Subject: [PATCH 4/6] source3/lib/access.c: Replace s3 strnequal with top level
 strncasecmp_m.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12419

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/lib/access.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/source3/lib/access.c b/source3/lib/access.c
index 2875b03..5e5f43f 100644
--- a/source3/lib/access.c
+++ b/source3/lib/access.c
@@ -192,11 +192,11 @@ bool client_match(const char *tok, const void *item)
 	 * Bug #5311 and #7383.
 	 */
 
-	if (strnequal(tok_addr, "::ffff:",7)) {
+	if (strncasecmp_m(tok_addr, "::ffff:",7) == 0) {
 		tok_addr += 7;
 	}
 
-	if (strnequal(cli_addr,"::ffff:",7)) {
+	if (strncasecmp_m(cli_addr,"::ffff:",7) == 0) {
 		cli_addr += 7;
 	}
 
-- 
2.7.4


>From 98d60c748e0255baa9ed468321c7bb5a3756351d Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 10 Nov 2016 17:15:20 -0800
Subject: [PATCH 5/6] Move source3/lib/access.c to toplevel lib/util/access.c

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12419

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 lib/util/access.c       | 349 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/util/access.h       |  24 ++++
 lib/util/wscript_build  |   5 +
 source3/include/proto.h |  10 +-
 source3/lib/access.c    | 344 -----------------------------------------------
 source3/wscript_build   |   3 +-
 6 files changed, 381 insertions(+), 354 deletions(-)
 create mode 100644 lib/util/access.c
 create mode 100644 lib/util/access.h
 delete mode 100644 source3/lib/access.c

diff --git a/lib/util/access.c b/lib/util/access.c
new file mode 100644
index 0000000..e73f1b7
--- /dev/null
+++ b/lib/util/access.c
@@ -0,0 +1,349 @@
+/*
+   This module is an adaption of code from the tcpd-1.4 package written
+   by Wietse Venema, Eindhoven University of Technology, The Netherlands.
+
+   The code is used here with permission.
+
+   The code has been considerably changed from the original. Bug reports
+   should be sent to samba-technical at lists.samba.org
+
+   Updated for IPv6 by Jeremy Allison (C) 2007.
+*/
+
+#include "includes.h"
+#include "../lib/util/memcache.h"
+#include "lib/socket/interfaces.h"
+#include "lib/util/samba_util.h"
+#include "lib/util/util_net.h"
+#include "lib/util/samba_util.h"
+#include "lib/util/memory.h"
+#include "lib/util/access.h"
+#include "lib/util/unix_match.h"
+
+#define NAME_INDEX 0
+#define ADDR_INDEX 1
+
+/* masked_match - match address against netnumber/netmask */
+static bool masked_match(const char *tok, const char *slash, const char *s)
+{
+	struct sockaddr_storage ss_mask;
+	struct sockaddr_storage ss_tok;
+	struct sockaddr_storage ss_host;
+	char *tok_copy = NULL;
+
+	if (!interpret_string_addr(&ss_host, s, 0)) {
+		return false;
+	}
+
+	if (*tok == '[') {
+		/* IPv6 address - remove braces. */
+		tok_copy = smb_xstrdup(tok+1);
+		if (!tok_copy) {
+			return false;
+		}
+		/* Remove the terminating ']' */
+		tok_copy[PTR_DIFF(slash,tok)-1] = '\0';
+	} else {
+		tok_copy = smb_xstrdup(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)) {
+		SAFE_FREE(tok_copy);
+		return false;
+	}
+
+	SAFE_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 s against token tok */
+static bool string_match(const char *tok,const char *s)
+{
+	size_t     tok_len;
+	size_t     str_len;
+	const char   *cut;
+
+	/* Return true if a token has the magic value "ALL". Return
+	 * true if the token is "FAIL". If the token starts with a "."
+	 * (domain name), return true if it matches the last fields of
+	 * the string. If the token has the magic value "LOCAL",
+	 * return true if the string does not contain a "."
+	 * character. If the token ends on a "." (network number),
+	 * return true if it matches the first fields of the
+	 * string. If the token begins with a "@" (netgroup name),
+	 * return true if the string is a (host) member of the
+	 * netgroup. Return true if the token fully matches the
+	 * string. If the token is a netnumber/netmask pair, return
+	 * true if the address is a member of the specified subnet.
+	 */
+
+	if (tok[0] == '.') {			/* domain: match last fields */
+		if ((str_len = strlen(s)) > (tok_len = strlen(tok))
+		    && strequal_m(tok, s + str_len - tok_len)) {
+			return true;
+		}
+	} else if (tok[0] == '@') { /* netgroup: look it up */
+#ifdef	HAVE_NETGROUP
+		DATA_BLOB tmp;
+		char *mydomain = NULL;
+		char *hostname = NULL;
+		bool netgroup_ok = false;
+
+		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"));
+		}
+		if (!(hostname = smb_xstrdup(s))) {
+			DEBUG(1,("out of memory for strdup!\n"));
+			return false;
+		}
+
+		netgroup_ok = innetgr(tok + 1, hostname, (char *) 0, mydomain);
+
+		DEBUG(5,("looking for %s of domain %s in netgroup %s gave %s\n",
+			 hostname,
+			 mydomain?mydomain:"(ANY)",
+			 tok+1,
+			 BOOLSTR(netgroup_ok)));
+
+		SAFE_FREE(hostname);
+
+		if (netgroup_ok)
+			return true;
+#else
+		DEBUG(0,("access: netgroup support is not configured\n"));
+		return false;
+#endif
+	} else if (strequal_m(tok, "ALL")) {	/* all: match any */
+		return true;
+	} else if (strequal_m(tok, "FAIL")) {	/* fail: match any */
+		return true;
+	} else if (strequal_m(tok, "LOCAL")) {	/* local: no dots */
+		if (strchr_m(s, '.') == 0 && !strequal_m(s, "unknown")) {
+			return true;
+		}
+	} else if (strequal_m(tok, s)) {   /* match host name or address */
+		return true;
+	} else if (tok[(tok_len = strlen(tok)) - 1] == '.') {	/* network */
+		if (strncmp(tok, s, tok_len) == 0) {
+			return true;
+		}
+	} else if ((cut = strchr_m(tok, '/')) != 0) {	/* netnumber/netmask */
+		if ((isdigit(s[0]) && strchr_m(tok, '.') != NULL) ||
+			(tok[0] == '[' && cut > tok && cut[-1] == ']') ||
+			((isxdigit(s[0]) || s[0] == ':') &&
+				strchr_m(tok, ':') != NULL)) {
+			/* IPv4/netmask or
+			 * [IPv6:addr]/netmask or IPv6:addr/netmask */
+			return masked_match(tok, cut, s);
+		}
+	} else if (strchr_m(tok, '*') != 0 || strchr_m(tok, '?')) {
+		return unix_wild_match(tok, s);
+	}
+	return false;
+}
+
+/* client_match - match host name and address against token */
+bool client_match(const char *tok, const void *item)
+{
+	const char **client = discard_const_p(const char *, item);
+	const char *tok_addr = tok;
+	const char *cli_addr = client[ADDR_INDEX];
+
+	/*
+	 * tok and client[ADDR_INDEX] can be an IPv4 mapped to IPv6,
+	 * we try and match the IPv4 part of address only.
+	 * Bug #5311 and #7383.
+	 */
+
+	if (strncasecmp_m(tok_addr, "::ffff:",7) == 0) {
+		tok_addr += 7;
+	}
+
+	if (strncasecmp_m(cli_addr,"::ffff:",7) == 0) {
+		cli_addr += 7;
+	}
+
+	/*
+	 * Try to match the address first. If that fails, try to match the host
+	 * name if available.
+	 */
+
+	if (string_match(tok_addr, cli_addr)) {
+		return true;
+	}
+
+	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 */
+bool list_match(const char **list,const void *item,
+		bool (*match_fn)(const char *, const void *))
+{
+	bool match = false;
+
+	if (!list) {
+		return false;
+	}
+
+	/*
+	 * Process tokens one at a time. We have exhausted all possible matches
+	 * when we reach an "EXCEPT" token or the end of the list. If we do find
+	 * a match, look for an "EXCEPT" list and recurse to determine whether
+	 * the match is affected by any exceptions.
+	 */
+
+	for (; *list ; list++) {
+		if (strequal_m(*list, "EXCEPT")) {
+			/* EXCEPT: give up */
+			break;
+		}
+		if ((match = (*match_fn) (*list, item))) {
+			/* true or FAIL */
+			break;
+		}
+	}
+	/* Process exceptions to true or FAIL matches. */
+
+	if (match != false) {
+		while (*list  && !strequal_m(*list, "EXCEPT")) {
+			list++;
+		}
+
+		for (; *list; list++) {
+			if ((*match_fn) (*list, item)) {
+				/* Exception Found */
+				return false;
+			}
+		}
+	}
+
+	return match;
+}
+
+/* return true if access should be allowed */
+static bool allow_access_internal(const char **deny_list,
+				const char **allow_list,
+				const char *cname,
+				const char *caddr)
+{
+	const char *client[2];
+
+	client[NAME_INDEX] = cname;
+	client[ADDR_INDEX] = caddr;
+
+	/* if it is loopback then always allow unless specifically denied */
+	if (strcmp(caddr, "127.0.0.1") == 0 || strcmp(caddr, "::1") == 0) {
+		/*
+		 * If 127.0.0.1 matches both allow and deny then allow.
+		 * Patch from Steve Langasek vorlon at netexpress.net.
+		 */
+		if (deny_list &&
+			list_match(deny_list,client,client_match) &&
+				(!allow_list ||
+				!list_match(allow_list,client, client_match))) {
+			return false;
+		}
+		return true;
+	}
+
+	/* if theres no deny list and no allow list then allow access */
+	if ((!deny_list || *deny_list == 0) &&
+	    (!allow_list || *allow_list == 0)) {
+		return true;
+	}
+
+	/* if there is an allow list but no deny list then allow only hosts
+	   on the allow list */
+	if (!deny_list || *deny_list == 0) {
+		return(list_match(allow_list,client,client_match));
+	}
+
+	/* if theres a deny list but no allow list then allow
+	   all hosts not on the deny list */
+	if (!allow_list || *allow_list == 0) {
+		return(!list_match(deny_list,client,client_match));
+	}
+
+	/* if there are both types of list then allow all hosts on the
+           allow list */
+	if (list_match(allow_list,(const char *)client,client_match)) {
+		return true;
+	}
+
+	/* if there are both types of list and it's not on the allow then
+	   allow it if its not on the deny */
+	if (list_match(deny_list,(const char *)client,client_match)) {
+		return false;
+	}
+
+	return true;
+}
+
+/* return true if access should be allowed */
+bool allow_access(const char **deny_list,
+		const char **allow_list,
+		const char *cname,
+		const char *caddr)
+{
+	bool ret;
+	char *nc_cname = smb_xstrdup(cname);
+	char *nc_caddr = smb_xstrdup(caddr);
+
+	ret = allow_access_internal(deny_list, allow_list, nc_cname, nc_caddr);
+
+	DEBUG(ret ? 3 : 0,
+	      ("%s connection from %s (%s)\n",
+	       ret ? "Allowed" : "Denied", nc_cname, nc_caddr));
+
+	SAFE_FREE(nc_cname);
+	SAFE_FREE(nc_caddr);
+	return ret;
+}
diff --git a/lib/util/access.h b/lib/util/access.h
new file mode 100644
index 0000000..b4dce15
--- /dev/null
+++ b/lib/util/access.h
@@ -0,0 +1,24 @@
+/*
+   This module is an adaption of code from the tcpd-1.4 package written
+   by Wietse Venema, Eindhoven University of Technology, The Netherlands.
+
+   The code is used here with permission.
+
+   The code has been considerably changed from the original. Bug reports
+   should be sent to samba-technical at lists.samba.org
+
+   Updated for IPv6 by Jeremy Allison (C) 2007.
+*/
+
+#ifndef _UTIL_ACCESS_H_
+#define _UTIL_ACCESS_H_
+
+bool client_match(const char *tok, const void *item);
+bool list_match(const char **list,const void *item,
+		bool (*match_fn)(const char *, const void *));
+bool allow_access(const char **deny_list,
+		const char **allow_list,
+		const char *cname,
+		const char *caddr);
+
+#endif
diff --git a/lib/util/wscript_build b/lib/util/wscript_build
index e2ae411..41201a5 100755
--- a/lib/util/wscript_build
+++ b/lib/util/wscript_build
@@ -29,6 +29,11 @@ bld.SAMBA_SUBSYSTEM('close-low-fd',
                     deps='replace',
                     local_include=False)
 
+bld.SAMBA_SUBSYSTEM('access',
+                    source='access.c',
+                    deps='interfaces samba-util',
+                    local_include=False)
+
 samba_debug_add_deps = ''
 samba_debug_add_inc  = ''
 
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 2758dc5..33e3f6c 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -26,15 +26,7 @@
 #include <sys/types.h>
 #include <regex.h>
 
-/* The following definitions come from lib/access.c  */
-
-bool client_match(const char *tok, const void *item);
-bool list_match(const char **list,const void *item,
-		bool (*match_fn)(const char *, const void *));
-bool allow_access(const char **deny_list,
-		const char **allow_list,
-		const char *cname,
-		const char *caddr);
+#include "lib/util/access.h"
 
 /* The following definitions come from lib/adt_tree.c  */
 
diff --git a/source3/lib/access.c b/source3/lib/access.c
deleted file mode 100644
index 5e5f43f..0000000
--- a/source3/lib/access.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
-   This module is an adaption of code from the tcpd-1.4 package written
-   by Wietse Venema, Eindhoven University of Technology, The Netherlands.
-
-   The code is used here with permission.
-
-   The code has been considerably changed from the original. Bug reports
-   should be sent to samba-technical at lists.samba.org
-
-   Updated for IPv6 by Jeremy Allison (C) 2007.
-*/
-
-#include "includes.h"
-#include "../lib/util/memcache.h"
-#include "lib/socket/interfaces.h"
-#include "lib/util/samba_util.h"
-
-#define NAME_INDEX 0
-#define ADDR_INDEX 1
-
-/* masked_match - match address against netnumber/netmask */
-static bool masked_match(const char *tok, const char *slash, const char *s)
-{
-	struct sockaddr_storage ss_mask;
-	struct sockaddr_storage ss_tok;
-	struct sockaddr_storage ss_host;
-	char *tok_copy = NULL;
-
-	if (!interpret_string_addr(&ss_host, s, 0)) {
-		return false;
-	}
-
-	if (*tok == '[') {
-		/* IPv6 address - remove braces. */
-		tok_copy = smb_xstrdup(tok+1);
-		if (!tok_copy) {
-			return false;
-		}
-		/* Remove the terminating ']' */
-		tok_copy[PTR_DIFF(slash,tok)-1] = '\0';
-	} else {
-		tok_copy = smb_xstrdup(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)) {
-		SAFE_FREE(tok_copy);
-		return false;
-	}
-
-	SAFE_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 s against token tok */
-static bool string_match(const char *tok,const char *s)
-{
-	size_t     tok_len;
-	size_t     str_len;
-	const char   *cut;
-
-	/* Return true if a token has the magic value "ALL". Return
-	 * true if the token is "FAIL". If the token starts with a "."
-	 * (domain name), return true if it matches the last fields of
-	 * the string. If the token has the magic value "LOCAL",
-	 * return true if the string does not contain a "."
-	 * character. If the token ends on a "." (network number),
-	 * return true if it matches the first fields of the
-	 * string. If the token begins with a "@" (netgroup name),
-	 * return true if the string is a (host) member of the
-	 * netgroup. Return true if the token fully matches the
-	 * string. If the token is a netnumber/netmask pair, return
-	 * true if the address is a member of the specified subnet.
-	 */
-
-	if (tok[0] == '.') {			/* domain: match last fields */
-		if ((str_len = strlen(s)) > (tok_len = strlen(tok))
-		    && strequal_m(tok, s + str_len - tok_len)) {
-			return true;
-		}
-	} else if (tok[0] == '@') { /* netgroup: look it up */
-#ifdef	HAVE_NETGROUP
-		DATA_BLOB tmp;
-		char *mydomain = NULL;
-		char *hostname = NULL;
-		bool netgroup_ok = false;
-
-		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"));
-		}
-		if (!(hostname = smb_xstrdup(s))) {
-			DEBUG(1,("out of memory for strdup!\n"));
-			return false;
-		}
-
-		netgroup_ok = innetgr(tok + 1, hostname, (char *) 0, mydomain);
-
-		DEBUG(5,("looking for %s of domain %s in netgroup %s gave %s\n",
-			 hostname,
-			 mydomain?mydomain:"(ANY)",
-			 tok+1,
-			 BOOLSTR(netgroup_ok)));
-
-		SAFE_FREE(hostname);
-
-		if (netgroup_ok)
-			return true;
-#else
-		DEBUG(0,("access: netgroup support is not configured\n"));
-		return false;
-#endif
-	} else if (strequal_m(tok, "ALL")) {	/* all: match any */
-		return true;
-	} else if (strequal_m(tok, "FAIL")) {	/* fail: match any */
-		return true;
-	} else if (strequal_m(tok, "LOCAL")) {	/* local: no dots */
-		if (strchr_m(s, '.') == 0 && !strequal_m(s, "unknown")) {
-			return true;
-		}
-	} else if (strequal_m(tok, s)) {   /* match host name or address */
-		return true;
-	} else if (tok[(tok_len = strlen(tok)) - 1] == '.') {	/* network */
-		if (strncmp(tok, s, tok_len) == 0) {
-			return true;
-		}
-	} else if ((cut = strchr_m(tok, '/')) != 0) {	/* netnumber/netmask */
-		if ((isdigit(s[0]) && strchr_m(tok, '.') != NULL) ||
-			(tok[0] == '[' && cut > tok && cut[-1] == ']') ||
-			((isxdigit(s[0]) || s[0] == ':') &&
-				strchr_m(tok, ':') != NULL)) {
-			/* IPv4/netmask or
-			 * [IPv6:addr]/netmask or IPv6:addr/netmask */
-			return masked_match(tok, cut, s);
-		}
-	} else if (strchr_m(tok, '*') != 0 || strchr_m(tok, '?')) {
-		return unix_wild_match(tok, s);
-	}
-	return false;
-}
-
-/* client_match - match host name and address against token */
-bool client_match(const char *tok, const void *item)
-{
-	const char **client = discard_const_p(const char *, item);
-	const char *tok_addr = tok;
-	const char *cli_addr = client[ADDR_INDEX];
-
-	/*
-	 * tok and client[ADDR_INDEX] can be an IPv4 mapped to IPv6,
-	 * we try and match the IPv4 part of address only.
-	 * Bug #5311 and #7383.
-	 */
-
-	if (strncasecmp_m(tok_addr, "::ffff:",7) == 0) {
-		tok_addr += 7;
-	}
-
-	if (strncasecmp_m(cli_addr,"::ffff:",7) == 0) {
-		cli_addr += 7;
-	}
-
-	/*
-	 * Try to match the address first. If that fails, try to match the host
-	 * name if available.
-	 */
-
-	if (string_match(tok_addr, cli_addr)) {
-		return true;
-	}
-
-	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 */
-bool list_match(const char **list,const void *item,
-		bool (*match_fn)(const char *, const void *))
-{
-	bool match = false;
-
-	if (!list) {
-		return false;
-	}
-
-	/*
-	 * Process tokens one at a time. We have exhausted all possible matches
-	 * when we reach an "EXCEPT" token or the end of the list. If we do find
-	 * a match, look for an "EXCEPT" list and recurse to determine whether
-	 * the match is affected by any exceptions.
-	 */
-
-	for (; *list ; list++) {
-		if (strequal_m(*list, "EXCEPT")) {
-			/* EXCEPT: give up */
-			break;
-		}
-		if ((match = (*match_fn) (*list, item))) {
-			/* true or FAIL */
-			break;
-		}
-	}
-	/* Process exceptions to true or FAIL matches. */
-
-	if (match != false) {
-		while (*list  && !strequal_m(*list, "EXCEPT")) {
-			list++;
-		}
-
-		for (; *list; list++) {
-			if ((*match_fn) (*list, item)) {
-				/* Exception Found */
-				return false;
-			}
-		}
-	}
-
-	return match;
-}
-
-/* return true if access should be allowed */
-static bool allow_access_internal(const char **deny_list,
-				const char **allow_list,
-				const char *cname,
-				const char *caddr)
-{
-	const char *client[2];
-
-	client[NAME_INDEX] = cname;
-	client[ADDR_INDEX] = caddr;
-
-	/* if it is loopback then always allow unless specifically denied */
-	if (strcmp(caddr, "127.0.0.1") == 0 || strcmp(caddr, "::1") == 0) {
-		/*
-		 * If 127.0.0.1 matches both allow and deny then allow.
-		 * Patch from Steve Langasek vorlon at netexpress.net.
-		 */
-		if (deny_list &&
-			list_match(deny_list,client,client_match) &&
-				(!allow_list ||
-				!list_match(allow_list,client, client_match))) {
-			return false;
-		}
-		return true;
-	}
-
-	/* if theres no deny list and no allow list then allow access */
-	if ((!deny_list || *deny_list == 0) &&
-	    (!allow_list || *allow_list == 0)) {
-		return true;
-	}
-
-	/* if there is an allow list but no deny list then allow only hosts
-	   on the allow list */
-	if (!deny_list || *deny_list == 0) {
-		return(list_match(allow_list,client,client_match));
-	}
-
-	/* if theres a deny list but no allow list then allow
-	   all hosts not on the deny list */
-	if (!allow_list || *allow_list == 0) {
-		return(!list_match(deny_list,client,client_match));
-	}
-
-	/* if there are both types of list then allow all hosts on the
-           allow list */
-	if (list_match(allow_list,(const char *)client,client_match)) {
-		return true;
-	}
-
-	/* if there are both types of list and it's not on the allow then
-	   allow it if its not on the deny */
-	if (list_match(deny_list,(const char *)client,client_match)) {
-		return false;
-	}
-
-	return true;
-}
-
-/* return true if access should be allowed */
-bool allow_access(const char **deny_list,
-		const char **allow_list,
-		const char *cname,
-		const char *caddr)
-{
-	bool ret;
-	char *nc_cname = smb_xstrdup(cname);
-	char *nc_caddr = smb_xstrdup(caddr);
-
-	ret = allow_access_internal(deny_list, allow_list, nc_cname, nc_caddr);
-
-	DEBUG(ret ? 3 : 0,
-	      ("%s connection from %s (%s)\n",
-	       ret ? "Allowed" : "Denied", nc_cname, nc_caddr));
-
-	SAFE_FREE(nc_cname);
-	SAFE_FREE(nc_caddr);
-	return ret;
-}
diff --git a/source3/wscript_build b/source3/wscript_build
index 22e1a62..d6d2be2 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -334,7 +334,7 @@ bld.SAMBA3_SUBSYSTEM('samba3core',
                    lib/dumpcore.c
                    lib/interface.c
                    lib/username.c
-                   lib/access.c lib/smbrun.c
+                   lib/smbrun.c
                    lib/wins_srv.c
                    lib/substitute.c
                    lib/substitute_generic.c
@@ -374,6 +374,7 @@ bld.SAMBA3_SUBSYSTEM('samba3core',
                         messages_util
                         messages_dgm
                         talloc_report
+			access
                         TDB_LIB''')
 
 bld.SAMBA3_LIBRARY('smbd_shim',
-- 
2.7.4


>From 8074539d27c3c782dc07dd742af7d756ae6d7ac9 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 10 Nov 2016 20:33:17 -0800
Subject: [PATCH 6/6] source4: Change to use lib/util/access functions.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12419

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source4/dsdb/common/util.c       |   3 +-
 source4/lib/socket/access.c      | 237 +--------------------------------------
 source4/lib/socket/socket.h      |   3 -
 source4/lib/socket/wscript_build |   2 +-
 4 files changed, 5 insertions(+), 240 deletions(-)

diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index d1396e4..fffccbe 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -46,6 +46,7 @@
 #include "librpc/gen_ndr/irpc.h"
 #include "libds/common/flag_mapping.h"
 #include "../lib/util/util_runcmd.h"
+#include "lib/util/access.h"
 
 /*
   search the sam for the specified attributes in a specific domain, filter on
@@ -1869,7 +1870,7 @@ const char *samdb_client_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
 
 		allow_list[0] = l_subnet_name;
 
-		if (socket_allow_access(mem_ctx, NULL, allow_list, "", ip_address)) {
+		if (allow_access(NULL, allow_list, "", ip_address)) {
 			sites_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx,
 							   res->msgs[i],
 							   "siteObject");
diff --git a/source4/lib/socket/access.c b/source4/lib/socket/access.c
index adc8105..c019fd6 100644
--- a/source4/lib/socket/access.c
+++ b/source4/lib/socket/access.c
@@ -33,241 +33,8 @@
 #include "includes.h"
 #include "system/network.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;
-
-	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));
-		return false;
-	}
-	
-	return (addr & mask) == (net & mask);
-}
-
-/* string_match - match string against token */
-static bool string_match(TALLOC_CTX *mem_ctx, const char *tok,const char *s, char *invalid_char)
-{
-	size_t     tok_len;
-	size_t     str_len;
-	const char   *cut;
-
-	*invalid_char = '\0';
-
-	/* Return true if a token has the magic value "ALL". Return
-	 * FAIL if the token is "FAIL". If the token starts with a "."
-	 * (domain name), return true if it matches the last fields of
-	 * the string. If the token has the magic value "LOCAL",
-	 * return true if the string does not contain a "."
-	 * character. If the token ends on a "." (network number),
-	 * return true if it matches the first fields of the
-	 * string. If the token begins with a "@" (netgroup name),
-	 * return true if the string is a (host) member of the
-	 * netgroup. Return true if the token fully matches the
-	 * string. If the token is a netnumber/netmask pair, return
-	 * true if the address is a member of the specified subnet.  
-	 */
-
-	if (tok[0] == '.') {			/* domain: match last fields */
-		if ((str_len = strlen(s)) > (tok_len = strlen(tok))
-		    && strcasecmp(tok, s + str_len - tok_len)==0) {
-			return true;
-		}
-	} else if (tok[0] == '@') { /* netgroup: look it up */
-		DEBUG(0,("access: netgroup support is not available\n"));
-		return false;
-	} else if (strcmp(tok, "ALL")==0) {	/* all: match any */
-		return true;
-	} else if (strcmp(tok, "FAIL")==0) {	/* fail: match any */
-		return FAIL;
-	} else if (strcmp(tok, "LOCAL")==0) {	/* local: no dots */
-		if (strchr(s, '.') == 0 && strcasecmp(s, "unknown") != 0) {
-			return true;
-		}
-	} else if (strcasecmp(tok, s)==0) {   /* match host name or address */
-		return true;
-	} else if (tok[(tok_len = strlen(tok)) - 1] == '.') {	/* network */
-		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))
-			return true;
-	} else if (strchr(tok, '*') != 0) {
-		*invalid_char = '*';
-	} else if (strchr(tok, '?') != 0) {
-		*invalid_char = '?';
-	}
-	return false;
-}
-
-struct client_addr {
-	const char *cname;
-	const char *caddr;
-};
-
-/* client_match - match host name and address against token */
-static bool client_match(TALLOC_CTX *mem_ctx, const char *tok, struct client_addr *client)
-{
-	bool match;
-	char invalid_char = '\0';
-
-	/*
-	 * Try to match the address first. If that fails, try to match the host
-	 * name if available.
-	 */
-
-	if ((match = string_match(mem_ctx, tok, client->caddr, &invalid_char)) == 0) {
-		if(invalid_char)
-			DEBUG(0,("client_match: address match failing due to invalid character '%c' found in \
-token '%s' in an allow/deny hosts line.\n", invalid_char, tok ));
-
-		if (client->cname[0] != 0)
-			match = string_match(mem_ctx, tok, client->cname, &invalid_char);
-
-		if(invalid_char)
-			DEBUG(0,("client_match: address match failing due to invalid character '%c' found in \
-token '%s' in an allow/deny hosts line.\n", invalid_char, tok ));
-	}
-
-	return (match);
-}
-
-/* list_match - match an item against a list of tokens with exceptions */
-static bool list_match(TALLOC_CTX *mem_ctx, const char **list, struct client_addr *client)
-{
-	bool match = false;
-
-	if (!list)
-		return false;
-
-	/*
-	 * Process tokens one at a time. We have exhausted all possible matches
-	 * when we reach an "EXCEPT" token or the end of the list. If we do find
-	 * a match, look for an "EXCEPT" list and recurse to determine whether
-	 * the match is affected by any exceptions.
-	 */
-
-	for (; *list ; list++) {
-		if (strcmp(*list, "EXCEPT")==0)	/* EXCEPT: give up */
-			break;
-		if ((match = client_match(mem_ctx, *list, client)))	/* true or FAIL */
-			break;
-	}
-
-	/* Process exceptions to true or FAIL matches. */
-	if (match != false) {
-		while (*list  && strcmp(*list, "EXCEPT")!=0)
-			list++;
-
-		for (; *list; list++) {
-			if (client_match(mem_ctx, *list, client)) /* Exception Found */
-				return false;
-		}
-	}
-
-	return match;
-}
-
-/* return true if access should be allowed */
-static bool allow_access_internal(TALLOC_CTX *mem_ctx,
-				  const char **deny_list,const char **allow_list,
-				  const char *cname, const char *caddr)
-{
-	struct client_addr client;
-
-	client.cname = cname;
-	client.caddr = caddr;
-
-	/* if it is loopback then always allow unless specifically denied */
-	if (strcmp(caddr, "127.0.0.1") == 0) {
-		/*
-		 * If 127.0.0.1 matches both allow and deny then allow.
-		 * Patch from Steve Langasek vorlon at netexpress.net.
-		 */
-		if (deny_list && 
-			list_match(mem_ctx, deny_list, &client) &&
-				(!allow_list ||
-				!list_match(mem_ctx, allow_list, &client))) {
-			return false;
-		}
-		return true;
-	}
-
-	/* if theres no deny list and no allow list then allow access */
-	if ((!deny_list || *deny_list == 0) && 
-	    (!allow_list || *allow_list == 0)) {
-		return true;  
-	}
-
-	/* if there is an allow list but no deny list then allow only hosts
-	   on the allow list */
-	if (!deny_list || *deny_list == 0)
-		return list_match(mem_ctx, allow_list, &client);
-
-	/* if theres a deny list but no allow list then allow
-	   all hosts not on the deny list */
-	if (!allow_list || *allow_list == 0)
-		return !list_match(mem_ctx, deny_list, &client);
-
-	/* if there are both types of list then allow all hosts on the
-           allow list */
-	if (list_match(mem_ctx, allow_list, &client))
-		return true;
-
-	/* if there are both types of list and it's not on the allow then
-	   allow it if its not on the deny */
-	if (list_match(mem_ctx, deny_list, &client))
-		return false;
-	
-	return true;
-}
-
-/* return true if access should be allowed */
-bool socket_allow_access(TALLOC_CTX *mem_ctx,
-			 const char **deny_list, const char **allow_list,
-			 const char *cname, const char *caddr)
-{
-	bool ret;
-	char *nc_cname = talloc_strdup(mem_ctx, cname);
-	char *nc_caddr = talloc_strdup(mem_ctx, caddr);
-
-	if (!nc_cname || !nc_caddr) {
-		return false;
-	}
-	
-	ret = allow_access_internal(mem_ctx, deny_list, allow_list, nc_cname, nc_caddr);
-
-	talloc_free(nc_cname);
-	talloc_free(nc_caddr);
-
-	return ret;
-}
+#include "lib/util/access.h"
 
 /* return true if the char* contains ip addrs only.  Used to avoid 
 gethostbyaddr() calls */
@@ -346,7 +113,7 @@ bool socket_check_access(struct socket_context *sock,
 		return false;
 	}
 
-	ret = socket_allow_access(mem_ctx, deny_list, allow_list, name, addr->addr);
+	ret = allow_access(deny_list, allow_list, name, addr->addr);
 	
 	if (ret) {
 		DEBUG(2,("socket_check_access: Allowed connection to '%s' from %s (%s)\n", 
diff --git a/source4/lib/socket/socket.h b/source4/lib/socket/socket.h
index 403a723..50a20d9 100644
--- a/source4/lib/socket/socket.h
+++ b/source4/lib/socket/socket.h
@@ -183,9 +183,6 @@ _PUBLIC_ void socket_address_set_port(struct socket_address *a,
 struct socket_address *socket_address_copy(TALLOC_CTX *mem_ctx,
 					   const struct socket_address *oaddr);
 const struct socket_ops *socket_getops_byname(const char *name, enum socket_type type);
-bool socket_allow_access(TALLOC_CTX *mem_ctx,
-			 const char **deny_list, const char **allow_list,
-			 const char *cname, const char *caddr);
 bool socket_check_access(struct socket_context *sock, 
 			 const char *service_name,
 			 const char **allow_list, const char **deny_list);
diff --git a/source4/lib/socket/wscript_build b/source4/lib/socket/wscript_build
index 1cb89c6..e243824 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 access'
     )
 
-- 
2.7.4



More information about the samba-technical mailing list