summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2021-02-23 08:27:07 +0100
committerJeremy Allison <jra@samba.org>2021-04-06 22:29:34 +0000
commit57246e1f814a9f8b17e0d3889822f271400a6515 (patch)
tree92cd04c551e00b2a744915cee2357c2a4fb5e949 /source3
parent30e0cac46bbf005612fcc50d3959b3a0351e4442 (diff)
downloadsamba-57246e1f814a9f8b17e0d3889822f271400a6515.tar.gz
winbindd: Avoid deadlock in sam_name_to_sid()
"Unix Users" and "Unix Groups" can recurse into nsswitch and thus into winbind. In the binding process, we have winbindd_off(), but if we pass the lookupNames request to a forked lsad, lsad does not necessarily have that setting. So lsad might turn back to winbind, which could lead to a deadlock. Handle the nsswitch lookups in winbind. While there, also do the simple wellknown names and the "DOMAIN\" type 3 lookups directly in winbind. Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source3')
-rw-r--r--source3/winbindd/winbindd_samr.c71
1 files changed, 65 insertions, 6 deletions
diff --git a/source3/winbindd/winbindd_samr.c b/source3/winbindd/winbindd_samr.c
index d8cfeab8ecb..d64917df6aa 100644
--- a/source3/winbindd/winbindd_samr.c
+++ b/source3/winbindd/winbindd_samr.c
@@ -569,14 +569,71 @@ static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
struct rpc_pipe_client *lsa_pipe;
struct policy_handle lsa_policy = { 0 };
struct dom_sid sid;
- const char *dom_name;
+ const char *dom_name = domain_name;
enum lsa_SidType type;
TALLOC_CTX *tmp_ctx = talloc_stackframe();
- NTSTATUS status;
+ NTSTATUS status = NT_STATUS_NONE_MAPPED;
bool retry = false;
+ bool ok;
DBG_NOTICE("%s\\%s\n", domain_name, name);
+ if (strequal(domain_name, unix_users_domain_name())) {
+ struct passwd *pwd = NULL;
+
+ if (name[0] == '\0') {
+ sid_copy(&sid, &global_sid_Unix_Users);
+ type = SID_NAME_DOMAIN;
+ goto done;
+ }
+
+ pwd = Get_Pwnam_alloc(tmp_ctx, name);
+ if (pwd == NULL) {
+ goto fail;
+ }
+ ok = sid_compose(&sid, &global_sid_Unix_Users, pwd->pw_uid);
+ if (!ok) {
+ status = NT_STATUS_INTERNAL_ERROR;
+ goto fail;
+ }
+ type = SID_NAME_USER;
+ goto done;
+ }
+
+ if (strequal(domain_name, unix_groups_domain_name())) {
+ struct group *grp = NULL;
+
+ if (name[0] == '\0') {
+ sid_copy(&sid, &global_sid_Unix_Groups);
+ type = SID_NAME_DOMAIN;
+ goto done;
+ }
+
+ grp = getgrnam(name);
+ if (grp == NULL) {
+ goto fail;
+ }
+ ok = sid_compose(&sid, &global_sid_Unix_Groups, grp->gr_gid);
+ if (!ok) {
+ status = NT_STATUS_INTERNAL_ERROR;
+ goto fail;
+ }
+ type = SID_NAME_DOM_GRP;
+ goto done;
+ }
+
+ if (name[0] == '\0') {
+ sid_copy(&sid, &domain->sid);
+ type = SID_NAME_DOMAIN;
+ goto done;
+ }
+
+ ok = lookup_wellknown_name(mem_ctx, name, &sid, &dom_name);
+ if (ok) {
+ type = SID_NAME_WKN_GRP;
+ goto done;
+ }
+
again:
status = open_cached_internal_pipe_conn(domain,
NULL,
@@ -584,7 +641,7 @@ again:
&lsa_pipe,
&lsa_policy);
if (!NT_STATUS_IS_OK(status)) {
- goto done;
+ goto fail;
}
status = rpc_name_to_sid(tmp_ctx,
@@ -603,14 +660,15 @@ again:
}
if (!NT_STATUS_IS_OK(status)) {
- goto done;
+ goto fail;
}
+done:
if (pdom_name != NULL) {
*pdom_name = talloc_strdup(mem_ctx, dom_name);
if (*pdom_name == NULL) {
status = NT_STATUS_NO_MEMORY;
- goto done;
+ goto fail;
}
}
@@ -621,7 +679,8 @@ again:
*ptype = type;
}
-done:
+ status = NT_STATUS_OK;
+fail:
TALLOC_FREE(tmp_ctx);
return status;
}