[SCM] Samba Shared Repository - branch master updated

Samuel Cabrero scabrero at samba.org
Wed Dec 13 16:06:01 UTC 2023


The branch, master has been updated
       via  3a01ef710d4 tests: Add a test for the idmap_nss : use_upn setting
       via  086a90d52b0 idmap_nss: Install a messaging filter to reload the configuration
       via  a7a4d8e5333 idmap_nss: Add a parameter to use UPNs instead of plain names
       via  c8e4777a921 idmap_nss: Increase debug on failures
       via  de2f59c61a0 docs: Document idmap_nss "range" option
       via  8e1f2ee5f7c s3:winbind: Register a messaging filter foreach domain child
       via  c35937054cd s3:winbind: talloc the static locator child
       via  e3d0574d796 s3:winbind: talloc the static idmap child
      from  f642aff5544 buildtools: Remove ‘keep_underscore’ parameter

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 3a01ef710d4f0c11013214a4f8637ebdac8d9f5e
Author: Samuel Cabrero <scabrero at samba.org>
Date:   Tue Dec 12 21:17:50 2023 +0100

    tests: Add a test for the idmap_nss : use_upn setting
    
    Signed-off-by: Samuel Cabrero <scabrero at samba.org>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>
    
    Autobuild-User(master): Samuel Cabrero <scabrero at samba.org>
    Autobuild-Date(master): Wed Dec 13 16:05:19 UTC 2023 on atb-devel-224

commit 086a90d52b0c4bd388bf5707159ae1a727f8e400
Author: Samuel Cabrero <scabrero at samba.org>
Date:   Tue Dec 12 16:02:33 2023 +0100

    idmap_nss: Install a messaging filter to reload the configuration
    
    Signed-off-by: Samuel Cabrero <scabrero at samba.org>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>

commit a7a4d8e53332f8cae68462afab7dec86c991d96f
Author: Samuel Cabrero <scabrero at suse.de>
Date:   Mon Nov 27 08:05:29 2023 +0100

    idmap_nss: Add a parameter to use UPNs instead of plain names
    
    idmap config <DOMAIN> : backend = nss
    idmap config <DOMAIN> : use_upn = yes|no
    
    When translating a Unix ID to a SID the module calls get[pwu|grg]id() but the
    name returned by some NSS modules might be a UPN instead of a plain name. If
    the new parameter is enabled the returned name will be parsed and correctly
    handled.
    
    On the other hand, when translating a SID to a Unix ID the module first
    resolves the SID to a domain + name, and then calls get[pw|gr]name() with the
    plain name, or the UPN if the new parameter is enabled.
    
    Signed-off-by: Samuel Cabrero <scabrero at samba.org>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>

commit c8e4777a921132082ee6421b2b456c82028fed46
Author: Samuel Cabrero <scabrero at samba.org>
Date:   Wed Nov 29 12:55:13 2023 +0100

    idmap_nss: Increase debug on failures
    
    Signed-off-by: Samuel Cabrero <scabrero at samba.org>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>

commit de2f59c61a0549c54546704c07a1f41410fc50d7
Author: Samuel Cabrero <scabrero at suse.de>
Date:   Mon Nov 27 10:20:05 2023 +0100

    docs: Document idmap_nss "range" option
    
    Signed-off-by: Samuel Cabrero <scabrero at samba.org>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>

commit 8e1f2ee5f7c5b3ee4edfa7beca289889a4e99cca
Author: Samuel Cabrero <scabrero at samba.org>
Date:   Tue Dec 12 15:55:20 2023 +0100

    s3:winbind: Register a messaging filter foreach domain child
    
    Instead of registering the "classic" callback for MSG_SMB_CONF_UPDATED,
    install a message filter to allow other parts of the code to also
    listen for this message because classic callbacks are delivered only
    once (see commit a2436b67e5dd47d955a3bea2b83e0693b627ab96).
    
    Signed-off-by: Samuel Cabrero <scabrero at samba.org>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>

commit c35937054cd69580bbf5e3252fd9a1e8958f2f7b
Author: Samuel Cabrero <scabrero at samba.org>
Date:   Tue Dec 12 15:49:07 2023 +0100

    s3:winbind: talloc the static locator child
    
    Next commits will use talloc_get_type_abort() to get the reference.
    
    Signed-off-by: Samuel Cabrero <scabrero at samba.org>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>

commit e3d0574d7969b00723a6b3041a796dd4f29726e8
Author: Samuel Cabrero <scabrero at samba.org>
Date:   Tue Dec 12 15:44:21 2023 +0100

    s3:winbind: talloc the static idmap child
    
    Next commits will use talloc_get_type_abort() to get the reference.
    
    Signed-off-by: Samuel Cabrero <scabrero at samba.org>
    Reviewed-by: Alexander Bokovoy <ab at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 docs-xml/manpages/idmap_nss.8.xml        |  38 +++++
 nsswitch/tests/test_idmap_nss_use_upn.sh |  79 ++++++++++
 source3/selftest/tests.py                |   4 +-
 source3/winbindd/idmap_nss.c             | 249 +++++++++++++++++++++++++++++--
 source3/winbindd/winbindd.c              |  13 +-
 source3/winbindd/winbindd_dual.c         |  34 +++--
 source3/winbindd/winbindd_idmap.c        |  29 ++--
 source3/winbindd/winbindd_locator.c      |  21 ++-
 source3/winbindd/winbindd_proto.h        |   4 +-
 9 files changed, 425 insertions(+), 46 deletions(-)
 create mode 100755 nsswitch/tests/test_idmap_nss_use_upn.sh


Changeset truncated at 500 lines:

diff --git a/docs-xml/manpages/idmap_nss.8.xml b/docs-xml/manpages/idmap_nss.8.xml
index fc03445df2c..a9c6eceedbc 100644
--- a/docs-xml/manpages/idmap_nss.8.xml
+++ b/docs-xml/manpages/idmap_nss.8.xml
@@ -27,6 +27,44 @@
 	</para>
 </refsynopsisdiv>
 
+<refsect1>
+	<title>IDMAP OPTIONS</title>
+
+	<variablelist>
+		<varlistentry>
+		<term>range = low - high</term>
+		<listitem><para>
+			Defines the available matching UID and GID range for which the
+			backend is authoritative. Note that the range acts as a filter.
+			Returned UIDs or GIDs by NSS modules that fall outside the range
+			are ignored and the corresponding maps discarded. It is intended
+			as a way to avoid accidental UID/GID overlaps between local and
+			remotely defined IDs.
+		</para></listitem>
+		</varlistentry>
+
+		<varlistentry>
+		<term>use_upn = <yes | no></term>
+		<listitem>
+		<para>
+			Some NSS modules can return and handle UPNs and/or down-level
+			logon names (e.g., DOMAIN\user or user at REALM).
+		</para>
+		<para>
+			If this parameter is enabled the returned names from NSS will be
+			parsed and the resulting namespace will be used as the authoritative
+			namespace instead of the IDMAP domain name. Also, down-level logon
+			names will be sent to NSS instead of the plain username to give NSS
+			modules a hint about the user's correct domain.
+		</para>
+		<para>Default: no</para>
+		</listitem>
+		</varlistentry>
+
+	</variablelist>
+</refsect1>
+
+
 <refsect1>
 	<title>EXAMPLES</title>
 
diff --git a/nsswitch/tests/test_idmap_nss_use_upn.sh b/nsswitch/tests/test_idmap_nss_use_upn.sh
new file mode 100755
index 00000000000..df2c67203d8
--- /dev/null
+++ b/nsswitch/tests/test_idmap_nss_use_upn.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+wbinfo="$BINDIR/wbinfo"
+smbcontrol="$BINDIR/smbcontrol"
+net="$BINDIR/net"
+global_inject_conf=$(dirname $SMB_CONF_PATH)/global_inject.conf
+
+failed=0
+
+. $(dirname $0)/../../testprogs/blackbox/subunit.sh
+
+# Reset idmap_nss configuration and clear cache
+echo "idmap config $DOMAIN : use_upn = no" >$global_inject_conf
+$smbcontrol winbindd reload-config
+if [ $? -ne 0 ]; then
+	echo "Could not reload config" | subunit_fail_test "test_idmap_nss_use_upn"
+fi
+
+$net cache flush
+if [ $? -ne 0 ]; then
+	echo "Could not flush cache" | subunit_fail_test "test_idmap_nss_use_upn"
+fi
+
+# Get the user SID
+USER="bob"
+USER_SID=$($wbinfo --name-to-sid="$USER")
+if [ $? -ne 0 ]; then
+	echo "Could not find SID for user '$USER'" | subunit_fail_test "test_idmap_nss_use_upn"
+	exit 1
+fi
+
+USER_SID=$(echo $USER_SID | cut -d " " -f 1)
+if [ $? -ne 0 ]; then
+	echo "Could not find SID for user '$USER'" | subunit_fail_test "test_idmap_nss_use_upn"
+	exit 1
+fi
+
+testit "SID to UID (use_upn = no)" $wbinfo --sid-to-uid=${USER_SID} || failed=$(expr $failed + 1)
+
+echo "idmap config $DOMAIN : use_upn = yes" >$global_inject_conf
+$smbcontrol winbindd reload-config
+if [ $? -ne 0 ]; then
+	echo "Could not reload config" | subunit_fail_test "test_idmap_nss_use_upn"
+fi
+
+$net cache flush
+if [ $? -ne 0 ]; then
+	echo "Could not flush cache" | subunit_fail_test "test_idmap_nss_use_upn"
+fi
+
+# The following test will fail because idmap_nss will search ADDOMAIN/bob, which does not
+# exists in NSS_WRAPPER_PASSWD
+testit_expect_failure "SID to UID (use_upn = yes)" $wbinfo --sid-to-uid=${USER_SID} || failed=$(expr $failed + 1)
+
+$net cache flush
+if [ $? -ne 0 ]; then
+	echo "Could not flush cache" | subunit_fail_test "test_idmap_nss_use_upn"
+fi
+
+# Add the ADDOMAIN/bob temporarily
+ENTRY="$(getent passwd bob)"
+ENTRY="$DOMAIN/${ENTRY}"
+sed -i "1i ${ENTRY}" $NSS_WRAPPER_PASSWD
+testit "Get user UID (use_upn = yes)" $wbinfo --sid-to-uid=${USER_SID} || failed=$(expr $failed + 1)
+sed -i "1d" $NSS_WRAPPER_PASSWD
+
+# Reset config
+echo "idmap config $DOMAIN : use_upn = no" >$global_inject_conf
+$smbcontrol winbindd reload-config
+if [ $? -ne 0 ]; then
+	echo "Could not reload config" | subunit_fail_test "test_idmap_nss_use_upn"
+fi
+
+$net cache flush
+if [ $? -ne 0 ]; then
+	echo "Could not flush cache" | subunit_fail_test "test_idmap_nss_use_upn"
+fi
+
+exit $failed
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index 30740d66dcf..679ff4e9916 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -1106,7 +1106,7 @@ rpc = ["rpc.authcontext",
 
 local = ["local.nss"]
 
-idmap = ["idmap.rfc2307", "idmap.alloc", "idmap.rid", "idmap.ad"]
+idmap = ["idmap.rfc2307", "idmap.alloc", "idmap.rid", "idmap.ad", "idmap.nss"]
 
 rap = ["rap.basic", "rap.rpc", "rap.printing", "rap.sam"]
 
@@ -1217,6 +1217,8 @@ for t in tests:
                        '$DC_SERVER', '$DC_USERNAME', '$DC_PASSWORD'])
     elif t == "idmap.alloc":
         plantestsuite(t, "ad_member_rfc2307", [os.path.join(samba3srcdir, "../nsswitch/tests/test_idmap_nss.sh"), '$DOMAIN'])
+    elif t == "idmap.nss":
+        plantestsuite(t, "ad_member_idmap_nss:local", [os.path.join(samba3srcdir, "../nsswitch/tests/test_idmap_nss_use_upn.sh")])
     elif t == "idmap.rid":
         plantestsuite(t, "ad_member_idmap_rid", [os.path.join(samba3srcdir, "../nsswitch/tests/test_idmap_rid.sh"), '$DOMAIN', '2000000'])
         plantestsuite(t,
diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c
index 642d5141784..0af25362219 100644
--- a/source3/winbindd/idmap_nss.c
+++ b/source3/winbindd/idmap_nss.c
@@ -1,4 +1,4 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
 
    idmap NSS backend
@@ -26,16 +26,150 @@
 #include "idmap.h"
 #include "lib/winbind_util.h"
 #include "libcli/security/dom_sid.h"
+#include "lib/global_contexts.h"
+#include "messages.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_IDMAP
 
+struct idmap_nss_context {
+	struct idmap_domain *dom;
+	bool use_upn;
+};
+
+static int idmap_nss_context_destructor(struct idmap_nss_context *ctx)
+{
+	if ((ctx->dom != NULL) && (ctx->dom->private_data == ctx)) {
+		ctx->dom->private_data = NULL;
+	}
+	return 0;
+}
+
+static NTSTATUS idmap_nss_context_create(TALLOC_CTX *mem_ctx,
+					 struct idmap_domain *dom,
+					 struct idmap_nss_context **pctx)
+{
+	struct idmap_nss_context *ctx = NULL;
+
+	ctx = talloc_zero(mem_ctx, struct idmap_nss_context);
+	if (ctx == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+	ctx->dom = dom;
+
+	talloc_set_destructor(ctx, idmap_nss_context_destructor);
+
+	ctx->use_upn = idmap_config_bool(dom->name, "use_upn", false);
+
+	*pctx = ctx;
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS idmap_nss_get_context(struct idmap_domain *dom,
+				      struct idmap_nss_context **pctx)
+{
+	struct idmap_nss_context *ctx = NULL;
+	NTSTATUS status;
+
+	if (dom->private_data != NULL) {
+		*pctx = talloc_get_type_abort(dom->private_data,
+					      struct idmap_nss_context);
+		return NT_STATUS_OK;
+	}
+
+	status = idmap_nss_context_create(dom, dom, &ctx);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_WARNING("idmap_nss_context_create failed: %s\n",
+			    nt_errstr(status));
+		return status;
+	}
+
+	dom->private_data = ctx;
+	*pctx = ctx;
+	return NT_STATUS_OK;
+}
+
+static bool idmap_nss_msg_filter(struct messaging_rec *rec, void *private_data)
+{
+	struct idmap_domain *dom = talloc_get_type_abort(private_data,
+		       struct idmap_domain);
+	struct idmap_nss_context *ctx = NULL;
+	NTSTATUS status;
+	bool ret;
+
+	if (rec->msg_type == MSG_SMB_CONF_UPDATED) {
+		ret = lp_load_global(get_dyn_CONFIGFILE());
+		if (!ret) {
+			DBG_WARNING("Failed to reload configuration\n");
+			return false;
+		}
+
+		status = idmap_nss_get_context(dom, &ctx);
+		if (NT_STATUS_IS_ERR(status)) {
+			DBG_WARNING("Failed to get idmap nss context: %s\n",
+					nt_errstr(status));
+			return false;
+		}
+
+		ctx->use_upn = idmap_config_bool(dom->name, "use_upn", false);
+	}
+
+	return false;
+}
+
 /*****************************
  Initialise idmap database.
 *****************************/
 
 static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom)
 {
+	struct idmap_nss_context *ctx = NULL;
+	NTSTATUS status;
+	struct messaging_context *msg_ctx = global_messaging_context();
+	struct tevent_req *req = NULL;
+
+	status = idmap_nss_context_create(dom, dom, &ctx);
+	if (NT_STATUS_IS_ERR(status)) {
+		return status;
+	}
+
+	dom->private_data = ctx;
+
+	req = messaging_filtered_read_send(
+			dom,
+			messaging_tevent_context(msg_ctx),
+			msg_ctx,
+			idmap_nss_msg_filter,
+			dom);
+	if (req == NULL) {
+		DBG_WARNING("messaging_filtered_read_send failed\n");
+		return NT_STATUS_UNSUCCESSFUL;
+	}
+
+	return status;
+}
+
+static NTSTATUS idmap_nss_lookup_name(const char *namespace,
+				      const char *username,
+				      struct dom_sid *sid,
+				      enum lsa_SidType *type)
+{
+	bool ret;
+
+	/*
+	 * By default calls to winbindd are disabled
+	 * the following call will not recurse so this is safe
+	 */
+	(void)winbind_on();
+	ret = winbind_lookup_name(namespace, username, sid, type);
+	(void)winbind_off();
+
+	if (!ret) {
+		DBG_NOTICE("Failed to lookup name [%s] in namespace [%s]\n",
+			   username, namespace);
+		return NT_STATUS_NOT_FOUND;
+	}
+
 	return NT_STATUS_OK;
 }
 
@@ -45,8 +179,17 @@ static NTSTATUS idmap_nss_int_init(struct idmap_domain *dom)
 
 static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
 {
+	struct idmap_nss_context *ctx = NULL;
+	NTSTATUS status;
 	int i;
 
+	status = idmap_nss_get_context(dom, &ctx);
+	if (NT_STATUS_IS_ERR(status)) {
+		DBG_WARNING("Failed to get idmap nss context: %s\n",
+			    nt_errstr(status));
+		return status;
+	}
+
 	/* initialize the status to avoid surprise */
 	for (i = 0; ids[i]; i++) {
 		ids[i]->status = ID_UNKNOWN;
@@ -58,42 +201,89 @@ static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_ma
 		const char *name;
 		struct dom_sid sid;
 		enum lsa_SidType type;
-		bool ret;
 
 		switch (ids[i]->xid.type) {
 		case ID_TYPE_UID:
+			errno = 0;
 			pw = getpwuid((uid_t)ids[i]->xid.id);
-
 			if (!pw) {
+				DBG_DEBUG("getpwuid(%lu) failed: %s\n",
+					  (unsigned long)ids[i]->xid.id,
+					  errno != 0
+					  ? strerror(errno)
+					  : "not found");
 				ids[i]->status = ID_UNMAPPED;
 				continue;
 			}
 			name = pw->pw_name;
 			break;
 		case ID_TYPE_GID:
+			errno = 0;
 			gr = getgrgid((gid_t)ids[i]->xid.id);
-
 			if (!gr) {
+				DBG_DEBUG("getgrgid(%lu) failed: %s\n",
+					  (unsigned long)ids[i]->xid.id,
+					  errno != 0
+					  ? strerror(errno)
+					  : "not found");
 				ids[i]->status = ID_UNMAPPED;
 				continue;
 			}
 			name = gr->gr_name;
 			break;
 		default: /* ?? */
+			DBG_WARNING("Unexpected xid type %d\n",
+				    ids[i]->xid.type);
 			ids[i]->status = ID_UNKNOWN;
 			continue;
 		}
 
-		/* by default calls to winbindd are disabled
-		   the following call will not recurse so this is safe */
-		(void)winbind_on();
 		/* Lookup name from PDC using lsa_lookup_names() */
-		ret = winbind_lookup_name(dom->name, name, &sid, &type);
-		(void)winbind_off();
+		if (ctx->use_upn) {
+			char *p = NULL;
+			const char *namespace = NULL;
+			const char *domname = NULL;
+			const char *domuser = NULL;
+
+			p = strstr(name, lp_winbind_separator());
+			if (p != NULL) {
+				*p = '\0';
+				domname = name;
+				namespace = domname;
+				domuser = p + 1;
+			} else {
+				p = strchr(name, '@');
+				if (p != NULL) {
+					*p = '\0';
+					namespace = p + 1;
+					domname = "";
+					domuser = name;
+				} else {
+					namespace = dom->name;
+					domuser = name;
+				}
+			}
 
-		if (!ret) {
-			/* TODO: how do we know if the name is really not mapped,
-			 * or something just failed ? */
+			DBG_DEBUG("Using namespace [%s] from UPN instead "
+				  "of [%s] to lookup the name [%s]\n",
+				  namespace, dom->name, domuser);
+
+			status = idmap_nss_lookup_name(namespace,
+						       domuser,
+						       &sid,
+						       &type);
+		} else {
+			status = idmap_nss_lookup_name(dom->name,
+						       name,
+						       &sid,
+						       &type);
+                }
+
+		if (NT_STATUS_IS_ERR(status)) {
+			/*
+			 * TODO: how do we know if the name is really
+			 * not mapped, or something just failed ?
+			 */
 			ids[i]->status = ID_UNMAPPED;
 			continue;
 		}
@@ -129,8 +319,17 @@ static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_ma
 
 static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
 {
+	struct idmap_nss_context *ctx = NULL;
+	NTSTATUS status;
 	int i;
 
+	status = idmap_nss_get_context(dom, &ctx);
+	if (NT_STATUS_IS_ERR(status)) {
+		DBG_WARNING("Failed to get idmap nss context: %s\n",
+			    nt_errstr(status));
+		return status;
+	}
+
 	/* initialize the status to avoid surprise */
 	for (i = 0; ids[i]; i++) {
 		ids[i]->status = ID_UNKNOWN;
@@ -143,6 +342,8 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma
 		const char *_name = NULL;
 		char *domain = NULL;
 		char *name = NULL;
+		char *fqdn = NULL;
+		char *sname = NULL;
 		bool ret;
 
 		/* by default calls to winbindd are disabled
@@ -173,13 +374,30 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma
 			continue;
 		}
 
+		if (ctx->use_upn) {
+			fqdn = talloc_asprintf(talloc_tos(),
+					       "%s%s%s",
+					       domain,
+					       lp_winbind_separator(),
+					       name);
+			if (fqdn == NULL) {
+				DBG_ERR("No memory\n");
+				ids[i]->status = ID_UNMAPPED;
+				continue;
+			}
+			DBG_DEBUG("Using UPN [%s] instead of plain name [%s]\n",
+				  fqdn, name);
+			sname = fqdn;
+		} else {
+			sname = name;
+		}
+
 		switch (type) {
 		case SID_NAME_USER: {
 			struct passwd *pw;
 
 			/* this will find also all lower case name and use username level */
-
-			pw = Get_Pwnam_alloc(talloc_tos(), name);
+			pw = Get_Pwnam_alloc(talloc_tos(), sname);
 			if (pw) {
 				ids[i]->xid.id = pw->pw_uid;
 				ids[i]->xid.type = ID_TYPE_UID;
@@ -193,7 +411,7 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma
 		case SID_NAME_ALIAS:
 		case SID_NAME_WKN_GRP:
 


-- 
Samba Shared Repository



More information about the samba-cvs mailing list