[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