summaryrefslogtreecommitdiff
path: root/source3/passdb/lookup_sid.c
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2006-02-03 22:19:41 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:06:23 -0500
commit0af1500fc0bafe61019f1b2ab1d9e1d369221240 (patch)
tree653fc2533795458d5f9696402285d9f14e527a21 /source3/passdb/lookup_sid.c
parent21a30a1346c9f9a25659a0cea0d276d8c2e6ddca (diff)
downloadsamba-0af1500fc0bafe61019f1b2ab1d9e1d369221240.tar.gz
samba-0af1500fc0bafe61019f1b2ab1d9e1d369221240.tar.bz2
samba-0af1500fc0bafe61019f1b2ab1d9e1d369221240.zip
r13316: Let the carnage begin....
Sync with trunk as off r13315 (This used to be commit 17e63ac4ed8325c0d44fe62b2442449f3298559f)
Diffstat (limited to 'source3/passdb/lookup_sid.c')
-rw-r--r--source3/passdb/lookup_sid.c831
1 files changed, 659 insertions, 172 deletions
diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c
index 4640eb6ae5..6266aa9cab 100644
--- a/source3/passdb/lookup_sid.c
+++ b/source3/passdb/lookup_sid.c
@@ -3,6 +3,7 @@
uid/user handling
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Gerald (Jerry) Carter 2003
+ Copyright (C) Volker Lendecke 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -67,7 +68,7 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
if (strequal(domain, get_global_sam_name())) {
/* It's our own domain, lookup the name in passdb */
- if (lookup_global_sam_name(name, &rid, &type)) {
+ if (lookup_global_sam_name(name, flags, &rid, &type)) {
sid_copy(&sid, get_global_sam_sid());
sid_append_rid(&sid, rid);
goto ok;
@@ -87,16 +88,31 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
goto failed;
}
- if (domain[0] != '\0') {
- /* An explicit domain name was given, here our last resort is
- * winbind. */
- if (winbind_lookup_name(domain, name, &sid, &type)) {
+ /* Try the explicit winbind lookup first, don't let it guess the
+ * domain yet at this point yet. This comes later. */
+
+ if ((domain[0] != '\0') &&
+ (winbind_lookup_name(domain, name, &sid, &type))) {
+ goto ok;
+ }
+
+ if (strequal(domain, unix_users_domain_name())) {
+ if (lookup_unix_user_name(name, &sid)) {
+ type = SID_NAME_USER;
+ goto ok;
+ }
+ goto failed;
+ }
+
+ if (strequal(domain, unix_groups_domain_name())) {
+ if (lookup_unix_group_name(name, &sid)) {
+ type = SID_NAME_DOM_GRP;
goto ok;
}
goto failed;
}
- if (!(flags & LOOKUP_NAME_ISOLATED)) {
+ if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
goto failed;
}
@@ -176,7 +192,7 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
/* Both cases are done by looking at our passdb */
- if (lookup_global_sam_name(name, &rid, &type)) {
+ if (lookup_global_sam_name(name, flags, &rid, &type)) {
domain = talloc_strdup(tmp_ctx, get_global_sam_name());
sid_copy(&sid, get_global_sam_sid());
sid_append_rid(&sid, rid);
@@ -232,6 +248,22 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
}
/* 10. Don't translate */
+
+ /* 11. Ok, windows would end here. Samba has two more options:
+ Unmapped users and unmapped groups */
+
+ if (lookup_unix_user_name(name, &sid)) {
+ domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
+ type = SID_NAME_USER;
+ goto ok;
+ }
+
+ if (lookup_unix_group_name(name, &sid)) {
+ domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
+ type = SID_NAME_DOM_GRP;
+ goto ok;
+ }
+
failed:
talloc_free(tmp_ctx);
return False;
@@ -265,113 +297,513 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
return True;
}
-/*****************************************************************
- *THE CANONICAL* convert SID to name function.
- Tries local lookup first - for local sids, then tries winbind.
-*****************************************************************/
+static BOOL winbind_lookup_rids(TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ int num_rids, uint32 *rids,
+ const char **domain_name,
+ const char **names, uint32 *types)
+{
+ /* Unless the winbind interface is upgraded, fall back to ask for
+ * individual sids. I imagine introducing a lookuprids operation that
+ * directly proxies to lsa_lookupsids to the correct DC. -- vl */
+
+ int i;
+ for (i=0; i<num_rids; i++) {
+ DOM_SID sid;
+
+ sid_copy(&sid, domain_sid);
+ sid_append_rid(&sid, rids[i]);
+
+ if (winbind_lookup_sid(mem_ctx, &sid,
+ *domain_name == NULL ?
+ domain_name : NULL,
+ &names[i], &types[i])) {
+ if ((names[i] == NULL) || ((*domain_name) == NULL)) {
+ return False;
+ }
+ } else {
+ types[i] = SID_NAME_UNKNOWN;
+ }
+ }
+ return True;
+}
-BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
- const char **ret_domain, const char **ret_name,
- enum SID_NAME_USE *ret_type)
+static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
+ int num_rids, uint32_t *rids,
+ const char **domain_name,
+ const char ***names, enum SID_NAME_USE **types)
{
- const char *domain = NULL;
- const char *name = NULL;
- enum SID_NAME_USE type;
- TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ int i;
- /* Check if this is our own sid. This should perhaps be done by
- winbind? For the moment handle it here. */
+ *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
+ *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids);
- if (tmp_ctx == NULL) {
- DEBUG(0, ("talloc_new failed\n"));
+ if ((*names == NULL) || (*types == NULL)) {
return False;
}
- if (sid_check_is_domain(sid)) {
- domain = talloc_strdup(tmp_ctx, get_global_sam_name());
- name = talloc_strdup(tmp_ctx, "");
- type = SID_NAME_DOMAIN;
- goto ok;
+ if (sid_check_is_domain(domain_sid)) {
+ NTSTATUS result;
+
+ if (*domain_name == NULL) {
+ *domain_name = talloc_strdup(
+ mem_ctx, get_global_sam_name());
+ }
+
+ if (*domain_name == NULL) {
+ return False;
+ }
+
+ become_root();
+ result = pdb_lookup_rids(domain_sid, num_rids, rids,
+ *names, *types);
+ unbecome_root();
+
+ return (NT_STATUS_IS_OK(result) ||
+ NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
+ NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
}
- if (sid_check_is_in_our_domain(sid)) {
- uint32 rid;
- SMB_ASSERT(sid_peek_rid(sid, &rid));
+ if (sid_check_is_builtin(domain_sid)) {
- /* For our own domain passdb is responsible */
- if (!lookup_global_sam_rid(tmp_ctx, rid, &name, &type)) {
- goto failed;
+ if (*domain_name == NULL) {
+ *domain_name = talloc_strdup(
+ mem_ctx, builtin_domain_name());
}
- domain = talloc_strdup(tmp_ctx, get_global_sam_name());
- goto ok;
+ if (*domain_name == NULL) {
+ return False;
+ }
+
+ for (i=0; i<num_rids; i++) {
+ if (lookup_builtin_rid(*names, rids[i],
+ &(*names)[i])) {
+ if ((*names)[i] == NULL) {
+ return False;
+ }
+ (*types)[i] = SID_NAME_ALIAS;
+ } else {
+ (*types)[i] = SID_NAME_UNKNOWN;
+ }
+ }
+ return True;
+ }
+
+ if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
+ for (i=0; i<num_rids; i++) {
+ DOM_SID sid;
+ sid_copy(&sid, domain_sid);
+ sid_append_rid(&sid, rids[i]);
+ if (lookup_wellknown_sid(mem_ctx, &sid,
+ domain_name, &(*names)[i])) {
+ if ((*names)[i] == NULL) {
+ return False;
+ }
+ (*types)[i] = SID_NAME_WKN_GRP;
+ } else {
+ (*types)[i] = SID_NAME_UNKNOWN;
+ }
+ }
+ return True;
+ }
+
+ if (sid_check_is_unix_users(domain_sid)) {
+ if (*domain_name == NULL) {
+ *domain_name = talloc_strdup(
+ mem_ctx, unix_users_domain_name());
+ }
+ for (i=0; i<num_rids; i++) {
+ (*names)[i] = talloc_strdup(
+ (*names), uidtoname(rids[i]));
+ (*types)[i] = SID_NAME_USER;
+ }
+ return True;
+ }
+
+ if (sid_check_is_unix_groups(domain_sid)) {
+ if (*domain_name == NULL) {
+ *domain_name = talloc_strdup(
+ mem_ctx, unix_groups_domain_name());
+ }
+ for (i=0; i<num_rids; i++) {
+ (*names)[i] = talloc_strdup(
+ (*names), gidtoname(rids[i]));
+ (*types)[i] = SID_NAME_DOM_GRP;
+ }
+ return True;
+ }
+
+ return winbind_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
+ domain_name, *names, *types);
+}
+
+/*
+ * Is the SID a domain as such? If yes, lookup its name.
+ */
+
+static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
+ const char **name)
+{
+ const char *tmp;
+ enum SID_NAME_USE type;
+
+ if (sid_check_is_domain(sid)) {
+ *name = talloc_strdup(mem_ctx, get_global_sam_name());
+ return True;
}
if (sid_check_is_builtin(sid)) {
+ *name = talloc_strdup(mem_ctx, builtin_domain_name());
+ return True;
+ }
- domain = talloc_strdup(tmp_ctx, builtin_domain_name());
+ if (sid_check_is_wellknown_domain(sid, &tmp)) {
+ *name = talloc_strdup(mem_ctx, tmp);
+ return True;
+ }
- /* Yes, W2k3 returns "BUILTIN" both as domain and name here */
- name = talloc_strdup(tmp_ctx, builtin_domain_name());
- type = SID_NAME_DOMAIN;
- goto ok;
+ if (sid->num_auths != 4) {
+ /* This can't be a domain */
+ return False;
}
- if (sid_check_is_in_builtin(sid)) {
- uint32 rid;
+ if (IS_DC) {
+ uint32 i, num_domains;
+ struct trustdom_info **domains;
- SMB_ASSERT(sid_peek_rid(sid, &rid));
+ /* This is relatively expensive, but it happens only on DCs
+ * and for SIDs that have 4 sub-authorities and thus look like
+ * domains */
- if (!lookup_builtin_rid(tmp_ctx, rid, &name)) {
- goto failed;
+ if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx,
+ &num_domains,
+ &domains))) {
+ return False;
}
- /* There's only aliases in S-1-5-32 */
- type = SID_NAME_ALIAS;
- domain = talloc_strdup(tmp_ctx, builtin_domain_name());
+ for (i=0; i<num_domains; i++) {
+ if (sid_equal(sid, &domains[i]->sid)) {
+ *name = talloc_strdup(mem_ctx,
+ domains[i]->name);
+ return True;
+ }
+ }
+ return False;
+ }
- goto ok;
+ if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
+ (type == SID_NAME_DOMAIN)) {
+ *name = tmp;
+ return True;
}
- if (winbind_lookup_sid(tmp_ctx, sid, &domain, &name, &type)) {
- goto ok;
+ return False;
+}
+
+/*
+ * This tries to implement the rather weird rules for the lsa_lookup level
+ * parameter.
+ *
+ * This is as close as we can get to what W2k3 does. With this we survive the
+ * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
+ * different, but I assume that's just being too liberal. For example, W2k3
+ * replies to everything else but the levels 1-6 with INVALID_PARAMETER
+ * whereas NT4 does the same as level 1 (I think). I did not fully test that
+ * with NT4, this is what w2k3 does.
+ *
+ * Level 1: Ask everywhere
+ * Level 2: Ask domain and trusted domains, no builtin and wkn
+ * Level 3: Only ask domain
+ * Level 4: W2k3ad: Only ask AD trusts
+ * Level 5: Don't lookup anything
+ * Level 6: Like 4
+ */
+
+static BOOL check_dom_sid_to_level(const DOM_SID *sid, int level)
+{
+ int ret = False;
+
+ switch(level) {
+ case 1:
+ ret = True;
+ break;
+ case 2:
+ ret = (!sid_check_is_builtin(sid) &&
+ !sid_check_is_wellknown_domain(sid, NULL));
+ break;
+ case 3:
+ case 4:
+ case 6:
+ ret = sid_check_is_domain(sid);
+ break;
+ case 5:
+ ret = False;
+ break;
}
- DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying "
- "special SIDs.\n", sid_string_static(sid)));
+ DEBUG(10, ("%s SID %s in level %d\n",
+ ret ? "Accepting" : "Rejecting",
+ sid_string_static(sid), level));
+ return ret;
+}
- if (lookup_wellknown_sid(tmp_ctx, sid, &domain, &name)) {
- type = SID_NAME_WKN_GRP;
- goto ok;
+/*
+ * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
+ * references to domains, it is explicitly made for this.
+ *
+ * This attempts to be as efficient as possible: It collects all SIDs
+ * belonging to a domain and hands them in bulk to the appropriate lookup
+ * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
+ * *hugely* from this. Winbind is going to be extended with a lookup_rids
+ * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
+ * appropriate DC.
+ */
+
+NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
+ const DOM_SID **sids, int level,
+ struct lsa_dom_info **ret_domains,
+ struct lsa_name_info **ret_names)
+{
+ TALLOC_CTX *tmp_ctx;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ struct lsa_name_info *name_infos;
+ struct lsa_dom_info *dom_infos;
+
+ int i, j;
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (tmp_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
}
- failed:
- DEBUG(10, ("Failed to lookup sid %s\n", sid_string_static(sid)));
+ name_infos = TALLOC_ARRAY(tmp_ctx, struct lsa_name_info, num_sids);
+ dom_infos = TALLOC_ZERO_ARRAY(tmp_ctx, struct lsa_dom_info,
+ MAX_REF_DOMAINS);
+ if ((name_infos == NULL) || (dom_infos == NULL)) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ /* First build up the data structures:
+ *
+ * dom_infos is a list of domains referenced in the list of
+ * SIDs. Later we will walk the list of domains and look up the RIDs
+ * in bulk.
+ *
+ * name_infos is a shadow-copy of the SIDs array to collect the real
+ * data.
+ *
+ * dom_info->idxs is an index into the name_infos array. The
+ * difficulty we have here is that we need to keep the SIDs the client
+ * asked for in the same order for the reply
+ */
+
+ for (i=0; i<num_sids; i++) {
+ DOM_SID sid;
+ uint32 rid;
+ const char *domain_name = NULL;
+
+ sid_copy(&sid, sids[i]);
+ name_infos[i].type = SID_NAME_USE_NONE;
+
+ if (lookup_as_domain(&sid, name_infos, &domain_name)) {
+ /* We can't push that through the normal lookup
+ * process, as this would reference illegal
+ * domains.
+ *
+ * For example S-1-5-32 would end up referencing
+ * domain S-1-5- with RID 32 which is clearly wrong.
+ */
+ if (domain_name == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ name_infos[i].rid = 0;
+ name_infos[i].type = SID_NAME_DOMAIN;
+ name_infos[i].name = NULL;
+
+ if (sid_check_is_builtin(&sid)) {
+ /* Yes, W2k3 returns "BUILTIN" both as domain
+ * and name here */
+ name_infos[i].name = talloc_strdup(
+ name_infos, builtin_domain_name());
+ if (name_infos[i].name == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ }
+ } else {
+ /* This is a normal SID with rid component */
+ if (!sid_split_rid(&sid, &rid)) {
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
+ }
+ }
+
+ if (!check_dom_sid_to_level(&sid, level)) {
+ name_infos[i].rid = 0;
+ name_infos[i].type = SID_NAME_UNKNOWN;
+ name_infos[i].name = NULL;
+ continue;
+ }
+
+ for (j=0; j<MAX_REF_DOMAINS; j++) {
+ if (!dom_infos[j].valid) {
+ break;
+ }
+ if (sid_equal(&sid, &dom_infos[j].sid)) {
+ break;
+ }
+ }
+
+ if (j == MAX_REF_DOMAINS) {
+ /* TODO: What's the right error message here? */
+ result = NT_STATUS_NONE_MAPPED;
+ goto done;
+ }
+
+ if (!dom_infos[j].valid) {
+ /* We found a domain not yet referenced, create a new
+ * ref. */
+ dom_infos[j].valid = True;
+ sid_copy(&dom_infos[j].sid, &sid);
+
+ if (domain_name != NULL) {
+ /* This name was being found above in the case
+ * when we found a domain SID */
+ dom_infos[j].name =
+ talloc_steal(dom_infos, domain_name);
+ } else {
+ /* lookup_rids will take care of this */
+ dom_infos[j].name = NULL;
+ }
+ }
+
+ name_infos[i].dom_idx = j;
+
+ if (name_infos[i].type == SID_NAME_USE_NONE) {
+ name_infos[i].rid = rid;
+
+ ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
+ &dom_infos[j].num_idxs);
+
+ if (dom_infos[j].idxs == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ }
+ }
+
+ /* Iterate over the domains found */
+
+ for (i=0; i<MAX_REF_DOMAINS; i++) {
+ uint32_t *rids;
+ const char **names;
+ enum SID_NAME_USE *types;
+ struct lsa_dom_info *dom = &dom_infos[i];
+
+ if (!dom->valid) {
+ /* No domains left, we're done */
+ break;
+ }
+
+ rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs);
+
+ if (rids == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (j=0; j<dom->num_idxs; j++) {
+ rids[j] = name_infos[dom->idxs[j]].rid;
+ }
+
+ if (!lookup_rids(tmp_ctx, &dom->sid,
+ dom->num_idxs, rids, &dom->name,
+ &names, &types)) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ talloc_steal(dom_infos, dom->name);
+
+ for (j=0; j<dom->num_idxs; j++) {
+ int idx = dom->idxs[j];
+ name_infos[idx].type = types[j];
+ if (types[j] != SID_NAME_UNKNOWN) {
+ name_infos[idx].name =
+ talloc_steal(name_infos, names[j]);
+ } else {
+ name_infos[idx].name = NULL;
+ }
+ }
+ }
+
+ *ret_domains = talloc_steal(mem_ctx, dom_infos);
+ *ret_names = talloc_steal(mem_ctx, name_infos);
+ result = NT_STATUS_OK;
+
+ done:
talloc_free(tmp_ctx);
- return False;
+ return result;
+}
- ok:
+/*****************************************************************
+ *THE CANONICAL* convert SID to name function.
+*****************************************************************/
- if ((domain == NULL) || (name == NULL)) {
- DEBUG(0, ("talloc failed\n"));
- talloc_free(tmp_ctx);
+BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+ const char **ret_domain, const char **ret_name,
+ enum SID_NAME_USE *ret_type)
+{
+ struct lsa_dom_info *domain;
+ struct lsa_name_info *name;
+ TALLOC_CTX *tmp_ctx;
+ BOOL ret = False;
+
+ tmp_ctx = talloc_new(mem_ctx);
+
+ if (tmp_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
return False;
}
+ if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
+ &domain, &name))) {
+ goto done;
+ }
+
+ if (name->type == SID_NAME_UNKNOWN) {
+ goto done;
+ }
+
if (ret_domain != NULL) {
- *ret_domain = talloc_steal(mem_ctx, domain);
+ *ret_domain = talloc_steal(mem_ctx, domain->name);
}
if (ret_name != NULL) {
- *ret_name = talloc_steal(mem_ctx, name);
+ *ret_name = talloc_steal(mem_ctx, name->name);
}
if (ret_type != NULL) {
- *ret_type = type;
+ *ret_type = name->type;
}
+ ret = True;
+
+ done:
+ if (ret) {
+ DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
+ sid_string_static(sid), domain->name,
+ name->name, name->type));
+ } else {
+ DEBUG(10, ("failed to lookup sid %s\n",
+ sid_string_static(sid)));
+ }
talloc_free(tmp_ctx);
- return True;
+ return ret;
}
/*****************************************************************
@@ -448,7 +880,7 @@ static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
Store uid to SID mapping in cache.
*****************************************************************/
-static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
+void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
{
struct uid_sid_cache *pc;
@@ -520,7 +952,7 @@ static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
Store gid to SID mapping in cache.
*****************************************************************/
-static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
+void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
{
struct gid_sid_cache *pc;
@@ -552,200 +984,255 @@ static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
*THE CANONICAL* convert uid_t to SID function.
*****************************************************************/
-NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid)
+void uid_to_sid(DOM_SID *psid, uid_t uid)
{
uid_t low, high;
+ uint32 rid;
ZERO_STRUCTP(psid);
if (fetch_sid_from_uid_cache(psid, uid))
- return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
+ return;
- /* DC's never use winbindd to resolve users outside the
- defined idmap range */
+ if (lp_idmap_uid(&low, &high) && (uid >= low) && (uid <= high) &&
+ winbind_uid_to_sid(psid, uid)) {
- if ( lp_server_role()==ROLE_DOMAIN_MEMBER
- || (lp_idmap_uid(&low, &high) && uid >= low && uid <= high) )
- {
- if (winbind_uid_to_sid(psid, uid)) {
-
- DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
- (unsigned int)uid, sid_string_static(psid)));
+ DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
+ (unsigned int)uid, sid_string_static(psid)));
+ goto done;
+ }
- if (psid)
- store_uid_sid_cache(psid, uid);
- return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
- }
+ if (pdb_uid_to_rid(uid, &rid)) {
+ /* This is a mapped user */
+ sid_copy(psid, get_global_sam_sid());
+ sid_append_rid(psid, rid);
+ goto done;
}
- if (!local_uid_to_sid(psid, uid)) {
- DEBUG(10,("uid_to_sid: local %u failed to map to sid\n", (unsigned int)uid ));
- return NT_STATUS_UNSUCCESSFUL;
+ if (pdb_rid_algorithm() && (uid < max_algorithmic_uid())) {
+ sid_copy(psid, get_global_sam_sid());
+ sid_append_rid(psid, algorithmic_pdb_uid_to_user_rid(uid));
+ goto done;
+ } else {
+ sid_copy(psid, &global_sid_Unix_Users);
+ sid_append_rid(psid, uid);
+ goto done;
}
-
+
+ done:
DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid,
sid_string_static(psid)));
store_uid_sid_cache(psid, uid);
- return NT_STATUS_OK;
+ return;
}
/*****************************************************************
*THE CANONICAL* convert gid_t to SID function.
*****************************************************************/
-NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid)
+void gid_to_sid(DOM_SID *psid, gid_t gid)
{
gid_t low, high;
ZERO_STRUCTP(psid);
if (fetch_sid_from_gid_cache(psid, gid))
- return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
+ return;
- /* DC's never use winbindd to resolve groups outside the
- defined idmap range */
+ if (lp_idmap_gid(&low, &high) && (gid >= low) && (gid <= high) &&
+ winbind_gid_to_sid(psid, gid)) {
- if ( lp_server_role()==ROLE_DOMAIN_MEMBER
- || (lp_idmap_gid(&low, &high) && gid >= low && gid <= high) )
- {
- if (winbind_gid_to_sid(psid, gid)) {
+ DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
+ (unsigned int)gid, sid_string_static(psid)));
+ goto done;
+ }
- DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
- (unsigned int)gid, sid_string_static(psid)));
-
- if (psid)
- store_gid_sid_cache(psid, gid);
- return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
- }
+ if (pdb_gid_to_sid(gid, psid)) {
+ /* This is a mapped group */
+ goto done;
}
- if (!local_gid_to_sid(psid, gid)) {
- DEBUG(10,("gid_to_sid: local %u failed to map to sid\n", (unsigned int)gid ));
- return NT_STATUS_UNSUCCESSFUL;
+ if (pdb_rid_algorithm() && (gid < max_algorithmic_gid())) {
+ sid_copy(psid, get_global_sam_sid());
+ sid_append_rid(psid, pdb_gid_to_group_rid(gid));
+ goto done;
+ } else {
+ sid_copy(psid, &global_sid_Unix_Groups);
+ sid_append_rid(psid, gid);
+ goto done;
}
-
+
+ done:
DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid,
sid_string_static(psid)));
store_gid_sid_cache(psid, gid);
- return NT_STATUS_OK;
+ return;
}
/*****************************************************************
*THE CANONICAL* convert SID to uid function.
*****************************************************************/
-NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid)
+BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
{
- enum SID_NAME_USE name_type;
+ enum SID_NAME_USE type;
+ uint32 rid;
+ gid_t gid;
if (fetch_uid_from_cache(puid, psid))
- return NT_STATUS_OK;
+ return True;
- /* if this is our SID then go straight to a local lookup */
-
- if ( sid_compare_domain(get_global_sam_sid(), psid) == 0 ) {
- DEBUG(10,("sid_to_uid: my domain (%s) - trying local.\n",
- sid_string_static(psid) ));
-
- if ( local_sid_to_uid(puid, psid, &name_type) )
- goto success;
-
- DEBUG(10,("sid_to_uid: local lookup failed\n"));
-
- return NT_STATUS_UNSUCCESSFUL;
+ if (fetch_gid_from_cache(&gid, psid)) {
+ return False;
}
-
- /* If it is not our local domain, only hope is winbindd */
- if ( !winbind_lookup_sid(NULL, psid, NULL, NULL, &name_type) ) {
- DEBUG(10,("sid_to_uid: winbind lookup for non-local sid %s failed\n",
- sid_string_static(psid) ));
-
- return NT_STATUS_UNSUCCESSFUL;
+ if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
+ uid_t uid = rid;
+ *puid = uid;
+ goto done;
}
- /* If winbindd does know the SID, ensure this is a user */
+ if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
+ union unid_t id;
+
+ if (pdb_sid_to_id(psid, &id, &type)) {
+ if (type != SID_NAME_USER) {
+ DEBUG(5, ("sid %s is a %s, expected a user\n",
+ sid_string_static(psid),
+ sid_type_lookup(type)));
+ return False;
+ }
+ *puid = id.uid;
+ goto done;
+ }
+ if (pdb_rid_algorithm() &&
+ algorithmic_pdb_rid_is_user(rid)) {
+ *puid = algorithmic_pdb_user_rid_to_uid(rid);
+ goto done;
+ }
- if (name_type != SID_NAME_USER) {
- DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a user (%u)\n",
- (unsigned int)name_type ));
- return NT_STATUS_INVALID_PARAMETER;
+ /* This was ours, but it was neither mapped nor
+ * algorithmic. Fail */
+ return False;
}
- /* get the uid. Has to work or else we are dead in the water */
+ if (winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
+
+ if (type != SID_NAME_USER) {
+ DEBUG(10, ("sid_to_uid: sid %s is a %s\n",
+ sid_string_static(psid),
+ sid_type_lookup(type)));
+ return False;
+ }
- if ( !winbind_sid_to_uid(puid, psid) ) {
- DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n",
- sid_string_static(psid)));
- return NT_STATUS_UNSUCCESSFUL;
+ if (!winbind_sid_to_uid(puid, psid)) {
+ DEBUG(5, ("sid_to_uid: winbind failed to allocate a "
+ "new uid for sid %s\n",
+ sid_string_static(psid)));
+ return False;
+ }
+ goto done;
}
-success:
+ /* TODO: Here would be the place to allocate both a gid and a uid for
+ * the SID in question */
+
+ return False;
+
+ done:
DEBUG(10,("sid_to_uid: %s -> %u\n", sid_string_static(psid),
(unsigned int)*puid ));
store_uid_sid_cache(psid, *puid);
-
- return NT_STATUS_OK;
+ return True;
}
+
/*****************************************************************
*THE CANONICAL* convert SID to gid function.
Group mapping is used for gids that maps to Wellknown SIDs
*****************************************************************/
-NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid)
+BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
{
- enum SID_NAME_USE name_type;
+ uint32 rid;
+ GROUP_MAP map;
+ union unid_t id;
+ enum SID_NAME_USE type;
+ uid_t uid;
if (fetch_gid_from_cache(pgid, psid))
- return NT_STATUS_OK;
+ return True;
- /*
- * First we must look up the name and decide if this is a group sid.
- * Group mapping can deal with foreign SIDs
- */
+ if (fetch_uid_from_cache(&uid, psid))
+ return False;
+
+ if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
+ gid_t gid = rid;
+ *pgid = gid;
+ goto done;
+ }
+
+ if (sid_check_is_in_builtin(psid) && pdb_getgrsid(&map, *psid)) {
+ *pgid = map.gid;
+ goto done;
+ }
- if ( local_sid_to_gid(pgid, psid, &name_type) )
- goto success;
+ if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
+ if (pdb_sid_to_id(psid, &id, &type)) {
+ if ((type != SID_NAME_DOM_GRP) &&
+ (type != SID_NAME_ALIAS)) {
+ DEBUG(5, ("sid %s is a %s, expected a group\n",
+ sid_string_static(psid),
+ sid_type_lookup(type)));
+ return False;
+ }
+ *pgid = id.gid;
+ goto done;
+ }
+ if (pdb_rid_algorithm() &&
+ !algorithmic_pdb_rid_is_user(rid)) {
+ /* This must be a group, presented as alias */
+ *pgid = pdb_group_rid_to_gid(rid);
+ goto done;
+ }
+ /* This was ours, but it was neither mapped nor
+ * algorithmic. Fail. */
+ return False;
+ }
- if (!winbind_lookup_sid(NULL, psid, NULL, NULL, &name_type)) {
- DEBUG(10,("sid_to_gid: no one knows the SID %s (tried local, then "
- "winbind)\n", sid_string_static(psid)));
+ if (!winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
+ DEBUG(11,("sid_to_gid: no one knows the SID %s (tried local, "
+ "then winbind)\n", sid_string_static(psid)));
- return NT_STATUS_UNSUCCESSFUL;
+ return False;
}
/* winbindd knows it; Ensure this is a group sid */
- if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS)
- && (name_type != SID_NAME_WKN_GRP))
- {
- DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n",
- (unsigned int)name_type ));
-
- /* winbindd is running and knows about this SID. Just the wrong type.
- Don't fallback to a local lookup here */
-
- return NT_STATUS_INVALID_PARAMETER;
+ if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
+ (type != SID_NAME_WKN_GRP)) {
+ DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is "
+ "a %s\n", sid_type_lookup(type)));
+ return False;
}
/* winbindd knows it and it is a type of group; sid_to_gid must succeed
or we are dead in the water */
if ( !winbind_sid_to_gid(pgid, psid) ) {
- DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid for sid %s\n",
- sid_string_static(psid)));
- return NT_STATUS_UNSUCCESSFUL;
+ DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid "
+ "for sid %s\n", sid_string_static(psid)));
+ return False;
}
-success:
+ done:
DEBUG(10,("sid_to_gid: %s -> %u\n", sid_string_static(psid),
(unsigned int)*pgid ));
store_gid_sid_cache(psid, *pgid);
- return NT_STATUS_OK;
+ return True;
}