1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-22 22:04:08 +03:00

winbindd: Make sam_sid_to_name use samr instead of lsa

Same argument as with name_to_sid: We don't need the lsa lookup
routing, and samr is less prone to deadlocking.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
Volker Lendecke 2021-02-23 11:49:16 +01:00 committed by Jeremy Allison
parent c06be36e60
commit 82e30f3203

View File

@ -710,73 +710,165 @@ static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
char **pname,
enum lsa_SidType *ptype)
{
struct rpc_pipe_client *lsa_pipe;
struct policy_handle lsa_policy = { 0 };
char *domain_name = NULL;
char *name = NULL;
enum lsa_SidType type;
struct rpc_pipe_client *samr_pipe = NULL;
struct dcerpc_binding_handle *h = NULL;
struct policy_handle dom_pol = { .handle_type = 0, };
const char *domain_name = "";
const char *name = "";
enum lsa_SidType type = SID_NAME_USE_NONE;
struct lsa_Strings names = { .count = 0, };
struct samr_Ids types = { .count = 0 };
struct dom_sid domain_sid;
uint32_t rid;
TALLOC_CTX *tmp_ctx = talloc_stackframe();
NTSTATUS status;
NTSTATUS status = NT_STATUS_NONE_MAPPED;
NTSTATUS result;
bool retry = false;
bool ok;
DEBUG(3,("sam_sid_to_name\n"));
/* Paranoia check */
if (!sid_check_is_in_builtin(sid) &&
!sid_check_is_builtin(sid) &&
!sid_check_is_in_our_sam(sid) &&
!sid_check_is_our_sam(sid) &&
!sid_check_is_in_unix_users(sid) &&
!sid_check_is_unix_users(sid) &&
!sid_check_is_in_unix_groups(sid) &&
!sid_check_is_unix_groups(sid) &&
!sid_check_is_in_wellknown_domain(sid)) {
struct dom_sid_buf buf;
DEBUG(0, ("sam_sid_to_name: possible deadlock - trying to "
"lookup SID %s\n",
dom_sid_str_buf(sid, &buf)));
status = NT_STATUS_NONE_MAPPED;
if (sid_check_is_unix_users(sid)) {
domain_name = unix_users_domain_name();
type = SID_NAME_DOMAIN;
goto done;
}
if (sid_check_is_in_unix_users(sid)) {
struct passwd *pwd = NULL;
ok = sid_peek_rid(sid, &rid);
if (!ok) {
goto fail;
}
pwd = getpwuid(rid);
if (pwd == NULL) {
goto fail;
}
domain_name = unix_users_domain_name();
name = talloc_strdup(tmp_ctx, pwd->pw_name);
if (name == NULL) {
status = NT_STATUS_NO_MEMORY;
goto fail;
}
type = SID_NAME_USER;
goto done;
}
if (sid_check_is_unix_groups(sid)) {
domain_name = unix_groups_domain_name();
type = SID_NAME_DOMAIN;
goto done;
}
if (sid_check_is_in_unix_groups(sid)) {
struct group *grp = NULL;
ok = sid_peek_rid(sid, &rid);
if (!ok) {
goto fail;
}
grp = getgrgid(rid);
if (grp == NULL) {
goto fail;
}
domain_name = unix_groups_domain_name();
name = talloc_strdup(tmp_ctx, grp->gr_name);
if (name == NULL) {
status = NT_STATUS_NO_MEMORY;
goto fail;
}
type = SID_NAME_DOM_GRP;
goto done;
}
ok = lookup_wellknown_sid(tmp_ctx, sid, &domain_name, &name);
if (ok) {
type = SID_NAME_WKN_GRP;
goto done;
}
if (dom_sid_equal(sid, &domain->sid)) {
domain_name = domain->name;
type = SID_NAME_DOMAIN;
goto done;
}
sid_copy(&domain_sid, sid);
ok = sid_split_rid(&domain_sid, &rid);
if (!ok) {
goto fail;
}
if (!dom_sid_equal(&domain_sid, &domain->sid)) {
goto fail;
}
again:
status = open_cached_internal_pipe_conn(domain,
NULL,
NULL,
&lsa_pipe,
&lsa_policy);
status = open_cached_internal_pipe_conn(
domain, &samr_pipe, &dom_pol, NULL, NULL);
if (!NT_STATUS_IS_OK(status)) {
goto done;
goto fail;
}
h = samr_pipe->binding_handle;
status = rpc_sid_to_name(tmp_ctx,
lsa_pipe,
&lsa_policy,
domain,
sid,
&domain_name,
&name,
&type);
status = dcerpc_samr_LookupRids(
h, tmp_ctx, &dom_pol, 1, &rid, &names, &types, &result);
if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
retry = true;
goto again;
}
if (!NT_STATUS_IS_OK(status)) {
DBG_DEBUG("dcerpc_samr_LookupRids failed: %s\n",
nt_errstr(status));
goto fail;
}
if (!NT_STATUS_IS_OK(result)) {
DBG_DEBUG("dcerpc_samr_LookupRids resulted in %s\n",
nt_errstr(result));
status = result;
goto fail;
}
domain_name = domain->name;
name = names.names[0].string;
type = types.ids[0];
if (name != NULL) {
char *normalized = NULL;
NTSTATUS nstatus = normalize_name_map(
tmp_ctx, domain_name, name, &normalized);
if (NT_STATUS_IS_OK(nstatus) ||
NT_STATUS_EQUAL(nstatus, NT_STATUS_FILE_RENAMED)) {
name = normalized;
}
}
done:
if (ptype) {
*ptype = type;
}
if (pname) {
*pname = talloc_move(mem_ctx, &name);
*pname = talloc_strdup(mem_ctx, name);
if (*pname == NULL) {
status = NT_STATUS_NO_MEMORY;
goto fail;
}
}
if (pdomain_name) {
*pdomain_name = talloc_move(mem_ctx, &domain_name);
*pdomain_name = talloc_strdup(mem_ctx, domain_name);
if (*pdomain_name == NULL) {
status = NT_STATUS_NO_MEMORY;
goto fail;
}
}
done:
status = NT_STATUS_OK;
fail:
TALLOC_FREE(tmp_ctx);
return status;
}