diff options
author | Volker Lendecke <vl@samba.org> | 2021-02-23 08:27:07 +0100 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2021-04-06 22:29:34 +0000 |
commit | 57246e1f814a9f8b17e0d3889822f271400a6515 (patch) | |
tree | 92cd04c551e00b2a744915cee2357c2a4fb5e949 /source3/winbindd/winbindd_samr.c | |
parent | 30e0cac46bbf005612fcc50d3959b3a0351e4442 (diff) | |
download | samba-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/winbindd/winbindd_samr.c')
-rw-r--r-- | source3/winbindd/winbindd_samr.c | 71 |
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; } |