summaryrefslogtreecommitdiff
path: root/source3/passdb
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
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')
-rw-r--r--source3/passdb/lookup_sid.c831
-rw-r--r--source3/passdb/machine_sid.c3
-rw-r--r--source3/passdb/passdb.c621
-rw-r--r--source3/passdb/pdb_get_set.c12
-rw-r--r--source3/passdb/pdb_interface.c444
-rw-r--r--source3/passdb/pdb_ldap.c1530
-rw-r--r--source3/passdb/pdb_nds.c9
-rw-r--r--source3/passdb/pdb_smbpasswd.c22
-rw-r--r--source3/passdb/pdb_tdb.c96
-rw-r--r--source3/passdb/secrets.c164
-rw-r--r--source3/passdb/util_builtin.c2
-rw-r--r--source3/passdb/util_unixsids.c94
-rw-r--r--source3/passdb/util_wellknown.c15
13 files changed, 2489 insertions, 1354 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;
}
diff --git a/source3/passdb/machine_sid.c b/source3/passdb/machine_sid.c
index 074a516bcb..d7cae06749 100644
--- a/source3/passdb/machine_sid.c
+++ b/source3/passdb/machine_sid.c
@@ -35,13 +35,14 @@ static DOM_SID *global_sam_sid=NULL;
Read a SID from a file. This is for compatibility with the old MACHINE.SID
style of SID storage
****************************************************************************/
+
static BOOL read_sid_from_file(const char *fname, DOM_SID *sid)
{
char **lines;
int numlines;
BOOL ret;
- lines = file_lines_load(fname, &numlines);
+ lines = file_lines_load(fname, &numlines,0);
if (!lines || numlines < 1) {
if (lines) file_lines_free(lines);
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c
index f9f6021d81..90a51d1cbd 100644
--- a/source3/passdb/passdb.c
+++ b/source3/passdb/passdb.c
@@ -350,34 +350,129 @@ NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd)
on the UNIX user. Pass in a RID if you have one
************************************************************/
-NTSTATUS pdb_init_sam_new(SAM_ACCOUNT **new_sam_acct, const char *username,
- uint32 rid)
+NTSTATUS pdb_init_sam_new(SAM_ACCOUNT **new_sam_acct, const char *username)
{
- NTSTATUS nt_status = NT_STATUS_NO_MEMORY;
+ NTSTATUS result;
struct passwd *pwd;
- BOOL ret;
-
- pwd = Get_Pwnam(username);
+ uint32 user_rid;
+ DOM_SID user_sid, group_sid;
+ TALLOC_CTX *mem_ctx;
+ enum SID_NAME_USE type;
- if (!pwd)
- return NT_STATUS_NO_SUCH_USER;
-
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(new_sam_acct, pwd))) {
- *new_sam_acct = NULL;
- return nt_status;
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
}
- /* see if we need to generate a new rid using the 2.2 algorithm */
- if ( rid == 0 && lp_enable_rid_algorithm() ) {
- DEBUG(10,("pdb_init_sam_new: no RID specified. Generating one via old algorithm\n"));
- rid = algorithmic_pdb_uid_to_user_rid(pwd->pw_uid);
+ pwd = Get_Pwnam_alloc(mem_ctx, username);
+
+ if (pwd == NULL) {
+ DEBUG(10, ("Could not find user %s\n", username));
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
}
-
- /* set the new SID */
-
- ret = pdb_set_user_sid_from_rid( *new_sam_acct, rid, PDB_SET );
-
- return (ret ? NT_STATUS_OK : NT_STATUS_NO_SUCH_USER);
+
+ result = pdb_init_sam_pw(new_sam_acct, pwd);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(10, ("pdb_init_sam_pw failed: %s\n", nt_errstr(result)));
+ goto done;
+ }
+
+ if (pdb_rid_algorithm()) {
+ if (!pdb_set_user_sid_from_rid(
+ *new_sam_acct,
+ algorithmic_pdb_uid_to_user_rid(pwd->pw_uid),
+ PDB_SET)) {
+ result = NT_STATUS_INTERNAL_ERROR;
+ goto done;
+ }
+ if (!pdb_set_group_sid_from_rid(
+ *new_sam_acct, pdb_gid_to_group_rid(pwd->pw_gid),
+ PDB_SET)) {
+ result = NT_STATUS_INTERNAL_ERROR;
+ goto done;
+ }
+ result = NT_STATUS_OK;
+ goto done;
+ }
+
+ /* No algorithmic mapping, meaning that we have to figure out the
+ * primary group SID according to group mapping and the user SID must
+ * be a newly allocated one */
+
+ if (!pdb_gid_to_sid(pwd->pw_gid, &group_sid)) {
+ struct group *grp;
+ GROUP_MAP map;
+
+ grp = getgrgid(pwd->pw_gid);
+ if (grp == NULL) {
+ DEBUG(1, ("Primary group %d of user %s does not "
+ "exist.\n", pwd->pw_gid, username));
+ result = NT_STATUS_INVALID_PRIMARY_GROUP;
+ goto done;
+ }
+
+ DEBUG(5, ("Primary group %s of user %s is not mapped to "
+ "a domain group, auto-mapping it\n",
+ grp->gr_name, username));
+ result = map_unix_group(grp, &map);
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(1, ("Failed to map group %s\n", grp->gr_name));
+ goto done;
+ }
+ sid_copy(&group_sid, &map.sid);
+ DEBUG(5, ("Mapped unix group %s to SID %s\n",
+ grp->gr_name, sid_string_static(&group_sid)));
+ }
+
+ /* Now check that it's actually a domain group and not something
+ * else */
+
+ if (!lookup_sid(mem_ctx, &group_sid, NULL, NULL, &type)) {
+ DEBUG(3, ("Could not lookup %s's primary group sid %s\n",
+ username, sid_string_static(&group_sid)));
+ result = NT_STATUS_INVALID_PRIMARY_GROUP;
+ goto done;
+ }
+
+ if (type != SID_NAME_DOM_GRP) {
+ DEBUG(3, ("Primary group for user %s is a %s and not a domain "
+ "group\n", username, sid_type_lookup(type)));
+ result = NT_STATUS_INVALID_PRIMARY_GROUP;
+ goto done;
+ }
+
+ if (!pdb_set_group_sid(*new_sam_acct, &group_sid, PDB_SET)) {
+ DEBUG(3, ("Could not set group SID\n"));
+ result = NT_STATUS_INTERNAL_ERROR;
+ goto done;
+ }
+
+ if (!pdb_new_rid(&user_rid)) {
+ DEBUG(3, ("Could not allocate a new RID\n"));
+ result = NT_STATUS_ACCESS_DENIED;
+ goto done;
+ }
+
+ sid_copy(&user_sid, get_global_sam_sid());
+ sid_append_rid(&user_sid, user_rid);
+
+ if (!pdb_set_user_sid(*new_sam_acct, &user_sid, PDB_SET)) {
+ DEBUG(3, ("pdb_set_user_sid failed\n"));
+ result = NT_STATUS_INTERNAL_ERROR;
+ goto done;
+ }
+
+ result = NT_STATUS_OK;
+
+ done:
+ if (!NT_STATUS_IS_OK(result) && (*new_sam_acct != NULL)) {
+ pdb_free_sam(new_sam_acct);
+ }
+
+ talloc_free(mem_ctx);
+ return result;
}
@@ -666,6 +761,11 @@ uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
}
+uid_t max_algorithmic_uid(void)
+{
+ return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
+}
+
/*******************************************************************
converts UNIX uid to an NT User RID.
********************************************************************/
@@ -686,6 +786,11 @@ gid_t pdb_group_rid_to_gid(uint32 group_rid)
return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
}
+gid_t max_algorithmic_gid(void)
+{
+ return pdb_group_rid_to_gid(0xffffffff);
+}
+
/*******************************************************************
converts NT Group RID to a UNIX uid.
@@ -732,129 +837,11 @@ BOOL algorithmic_pdb_rid_is_user(uint32 rid)
}
/*******************************************************************
- Look up a rid in the SAM we're responsible for (i.e. passdb)
- ********************************************************************/
-
-BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid, const char **name,
- enum SID_NAME_USE *psid_name_use)
-{
- SAM_ACCOUNT *sam_account = NULL;
- GROUP_MAP map;
- BOOL ret;
- DOM_SID sid;
-
- *psid_name_use = SID_NAME_UNKNOWN;
-
- DEBUG(5,("lookup_global_sam_rid: looking up RID %u.\n",
- (unsigned int)rid));
-
- sid_copy(&sid, get_global_sam_sid());
- sid_append_rid(&sid, rid);
-
- /* see if the passdb can help us with the name of the user */
- if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
- return False;
- }
-
- /* BEING ROOT BLLOCK */
- become_root();
- if (pdb_getsampwsid(sam_account, &sid)) {
- unbecome_root(); /* -----> EXIT BECOME_ROOT() */
- *name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
- *psid_name_use = SID_NAME_USER;
-
- pdb_free_sam(&sam_account);
-
- return True;
- }
- pdb_free_sam(&sam_account);
-
- ret = pdb_getgrsid(&map, sid);
- unbecome_root();
- /* END BECOME_ROOT BLOCK */
-
- if ( ret ) {
- if (map.gid!=(gid_t)-1) {
- DEBUG(5,("lookup_global_sam_rid: mapped group %s to "
- "gid %u\n", map.nt_name,
- (unsigned int)map.gid));
- } else {
- DEBUG(5,("lookup_global_sam_rid: mapped group %s to "
- "no unix gid. Returning name.\n",
- map.nt_name));
- }
-
- *name = talloc_strdup(mem_ctx, map.nt_name);
- *psid_name_use = map.sid_name_use;
- return True;
- }
-
- if (rid == DOMAIN_USER_RID_ADMIN) {
- *psid_name_use = SID_NAME_USER;
- *name = talloc_strdup(mem_ctx, "Administrator");
- return True;
- }
-
- if (algorithmic_pdb_rid_is_user(rid)) {
- uid_t uid;
- struct passwd *pw = NULL;
-
- DEBUG(5, ("assuming RID %u is a user\n", (unsigned)rid));
-
- uid = algorithmic_pdb_user_rid_to_uid(rid);
- pw = sys_getpwuid( uid );
-
- DEBUG(5,("lookup_global_sam_rid: looking up uid %u %s\n",
- (unsigned int)uid, pw ? "succeeded" : "failed" ));
-
- if ( !pw ) {
- *name = talloc_asprintf(mem_ctx, "unix_user.%u",
- (unsigned int)uid);
- } else {
- *name = talloc_strdup(mem_ctx, pw->pw_name );
- }
-
- DEBUG(5,("lookup_global_sam_rid: found user %s for rid %u\n",
- *name, (unsigned int)rid ));
-
- *psid_name_use = SID_NAME_USER;
-
- return ( pw != NULL );
- } else {
- gid_t gid;
- struct group *gr;
-
- DEBUG(5, ("assuming RID %u is a group\n", (unsigned)rid));
-
- gid = pdb_group_rid_to_gid(rid);
- gr = getgrgid(gid);
-
- DEBUG(5,("lookup_global_sam_rid: looking up gid %u %s\n",
- (unsigned int)gid, gr ? "succeeded" : "failed" ));
-
- if( !gr ) {
- *name = talloc_asprintf(mem_ctx, "unix_group.%u",
- (unsigned int)gid);
- } else {
- *name = talloc_strdup(mem_ctx, gr->gr_name);
- }
-
- DEBUG(5,("lookup_global_sam_rid: found group %s for rid %u\n",
- *name, (unsigned int)rid ));
-
- /* assume algorithmic groups are domain global groups */
-
- *psid_name_use = SID_NAME_DOM_GRP;
-
- return ( gr != NULL );
- }
-}
-
-/*******************************************************************
Convert a name into a SID. Used in the lookup name rpc.
********************************************************************/
-BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE *type)
+BOOL lookup_global_sam_name(const char *c_user, int flags, uint32_t *rid,
+ enum SID_NAME_USE *type)
{
fstring user;
SAM_ACCOUNT *sam_account = NULL;
@@ -877,7 +864,13 @@ BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE
/* BEGIN ROOT BLOCK */
become_root();
- if (pdb_getsampwnam(sam_account, user)) {
+
+ /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
+ * correctly in the case where foo also exists as a user. If the flag
+ * is set, don't look for users at all. */
+
+ if (((flags & LOOKUP_NAME_GROUP) == 0) &&
+ pdb_getsampwnam(sam_account, user)) {
const DOM_SID *user_sid;
unbecome_root();
@@ -891,15 +884,7 @@ BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE
}
sid_peek_rid(user_sid, rid);
-
- if (pdb_get_acct_ctrl(sam_account) &
- (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST)) {
- /* We have to filter them out in lsa_lookupnames,
- * indicate that this is not a real user. */
- *type = SID_NAME_COMPUTER;
- } else {
- *type = SID_NAME_USER;
- }
+ *type = SID_NAME_USER;
pdb_free_sam(&sam_account);
return True;
}
@@ -929,6 +914,8 @@ BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE
return True;
}
+ return False;
+
/* it's not a mapped group */
grp = getgrnam(user);
if(!grp) {
@@ -965,13 +952,14 @@ BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE
Change a password entry in the local smbpasswd file.
*************************************************************/
-BOOL local_password_change(const char *user_name, int local_flags,
+NTSTATUS local_password_change(const char *user_name, int local_flags,
const char *new_passwd,
char *err_str, size_t err_str_len,
char *msg_str, size_t msg_str_len)
{
SAM_ACCOUNT *sam_pass=NULL;
uint16 other_acb;
+ NTSTATUS result;
*err_str = '\0';
*msg_str = '\0';
@@ -985,14 +973,30 @@ BOOL local_password_change(const char *user_name, int local_flags,
pdb_free_sam(&sam_pass);
if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
- /* Might not exist in /etc/passwd. Use rid algorithm here */
- if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pass, user_name, 0))) {
- slprintf(err_str, err_str_len-1, "Failed to initialise SAM_ACCOUNT for user %s. Does this user exist in the UNIX password database ?\n", user_name);
- return False;
+ int tmp_debug = DEBUGLEVEL;
+
+ /* Might not exist in /etc/passwd. */
+
+ if (tmp_debug < 1) {
+ DEBUGLEVEL = 1;
+ }
+
+ result = pdb_init_sam_new(&sam_pass, user_name);
+ DEBUGLEVEL = tmp_debug;
+ if (NT_STATUS_EQUAL(result,
+ NT_STATUS_INVALID_PRIMARY_GROUP)) {
+ return result;
+ }
+
+ if (!NT_STATUS_IS_OK(result)) {
+ slprintf(err_str, err_str_len-1, "Failed to "
+ "initialize account for user %s: %s\n",
+ user_name, nt_errstr(result));
+ return result;
}
} else {
slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name);
- return False;
+ return NT_STATUS_NO_SUCH_USER;
}
} else {
unbecome_root();
@@ -1006,19 +1010,19 @@ BOOL local_password_change(const char *user_name, int local_flags,
if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) {
slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
} else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) {
slprintf(err_str, err_str_len - 1, "Failed to set 'domain trust account' flags for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
} else {
if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) {
slprintf(err_str, err_str_len - 1, "Failed to set 'normal account' flags for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
}
@@ -1031,13 +1035,13 @@ BOOL local_password_change(const char *user_name, int local_flags,
if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) {
slprintf(err_str, err_str_len-1, "Failed to set 'disabled' flag for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
} else if (local_flags & LOCAL_ENABLE_USER) {
if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
}
@@ -1045,7 +1049,7 @@ BOOL local_password_change(const char *user_name, int local_flags,
if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) {
slprintf(err_str, err_str_len-1, "Failed to set 'no password required' flag for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
} else if (local_flags & LOCAL_SET_PASSWORD) {
/*
@@ -1061,19 +1065,19 @@ BOOL local_password_change(const char *user_name, int local_flags,
if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
}
if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) {
slprintf(err_str, err_str_len-1, "Failed to unset 'no password required' flag for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
slprintf(err_str, err_str_len-1, "Failed to set password for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
}
@@ -1081,24 +1085,25 @@ BOOL local_password_change(const char *user_name, int local_flags,
if (pdb_add_sam_account(sam_pass)) {
slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
pdb_free_sam(&sam_pass);
- return True;
+ return NT_STATUS_OK;
} else {
slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
} else if (local_flags & LOCAL_DELETE_USER) {
if (!pdb_delete_sam_account(sam_pass)) {
slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
} else {
- if(!pdb_update_sam_account(sam_pass)) {
+ result = pdb_update_sam_account(sam_pass);
+ if(!NT_STATUS_IS_OK(result)) {
slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
- return False;
+ return result;
}
if(local_flags & LOCAL_DISABLE_USER)
slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name);
@@ -1109,232 +1114,7 @@ BOOL local_password_change(const char *user_name, int local_flags,
}
pdb_free_sam(&sam_pass);
- return True;
-}
-
-/****************************************************************************
- Convert a uid to SID - algorithmic.
-****************************************************************************/
-
-DOM_SID *algorithmic_uid_to_sid(DOM_SID *psid, uid_t uid)
-{
- if ( !lp_enable_rid_algorithm() )
- return NULL;
-
- DEBUG(8,("algorithmic_uid_to_sid: falling back to RID algorithm\n"));
- sid_copy( psid, get_global_sam_sid() );
- sid_append_rid( psid, algorithmic_pdb_uid_to_user_rid(uid) );
- DEBUG(10,("algorithmic_uid_to_sid: uid (%d) -> SID %s.\n",
- (unsigned int)uid, sid_string_static(psid) ));
-
- return psid;
-}
-
-/****************************************************************************
- Convert a uid to SID - locally.
-****************************************************************************/
-
-DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid)
-{
- SAM_ACCOUNT *sampw = NULL;
- struct passwd *unix_pw;
- BOOL ret;
-
- unix_pw = sys_getpwuid( uid );
-
- if ( !unix_pw ) {
- DEBUG(4,("local_uid_to_sid: host has no idea of uid %lu\n", (unsigned long)uid));
- return algorithmic_uid_to_sid( psid, uid);
- }
-
- if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) {
- DEBUG(0,("local_uid_to_sid: failed to allocate SAM_ACCOUNT object\n"));
- return NULL;
- }
-
- become_root();
- ret = pdb_getsampwnam( sampw, unix_pw->pw_name );
- unbecome_root();
-
- if ( ret )
- sid_copy( psid, pdb_get_user_sid(sampw) );
- else {
- DEBUG(4,("local_uid_to_sid: User %s [uid == %lu] has no samba account\n",
- unix_pw->pw_name, (unsigned long)uid));
-
- algorithmic_uid_to_sid( psid, uid);
- }
-
- pdb_free_sam(&sampw);
-
- DEBUG(10,("local_uid_to_sid: uid (%d) -> SID %s (%s).\n",
- (unsigned int)uid, sid_string_static(psid), unix_pw->pw_name));
-
- return psid;
-}
-
-/****************************************************************************
- Convert a SID to uid - locally.
-****************************************************************************/
-
-BOOL local_sid_to_uid(uid_t *puid, const DOM_SID *psid, enum SID_NAME_USE *name_type)
-{
- SAM_ACCOUNT *sampw = NULL;
- struct passwd *unix_pw;
- const char *user_name;
-
- *name_type = SID_NAME_UNKNOWN;
-
- /*
- * We can only convert to a uid if this is our local
- * Domain SID (ie. we are the controling authority).
- */
- if (!sid_check_is_in_our_domain(psid) ) {
- DEBUG(5,("local_sid_to_uid: this SID (%s) is not from our domain\n", sid_string_static(psid)));
- return False;
- }
-
- /* lookup the user account */
-
- if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) {
- DEBUG(0,("local_sid_to_uid: Failed to allocate memory for SAM_ACCOUNT object\n"));
- return False;
- }
-
- become_root();
- if ( !pdb_getsampwsid(sampw, psid) ) {
- unbecome_root();
- pdb_free_sam(&sampw);
- DEBUG(8,("local_sid_to_uid: Could not find SID %s in passdb\n",
- sid_string_static(psid)));
- return False;
- }
- unbecome_root();
-
- user_name = pdb_get_username(sampw);
-
- unix_pw = sys_getpwnam( user_name );
-
- if ( !unix_pw ) {
- DEBUG(0,("local_sid_to_uid: %s found in passdb but getpwnam() return NULL!\n",
- user_name));
- pdb_free_sam( &sampw );
- return False;
- }
-
- *puid = unix_pw->pw_uid;
-
- DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_string_static(psid),
- (unsigned int)*puid, user_name ));
-
- *name_type = SID_NAME_USER;
- pdb_free_sam( &sampw );
- return True;
-}
-
-/****************************************************************************
- Convert a gid to SID - locally.
-****************************************************************************/
-
-DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid)
-{
- GROUP_MAP group;
- BOOL ret;
-
- /* we don't need to disable winbindd since the gid is stored in
- the GROUP_MAP object */
-
- /* done as root since ldap backend requires root to open a connection */
-
- become_root();
- ret = pdb_getgrgid( &group, gid );
- unbecome_root();
-
- if ( !ret ) {
-
- /* fallback to rid mapping if enabled */
-
- if ( lp_enable_rid_algorithm() ) {
- sid_copy(psid, get_global_sam_sid());
- sid_append_rid(psid, pdb_gid_to_group_rid(gid));
-
- DEBUG(10,("local_gid_to_sid: Fall back to algorithmic mapping: %u -> %s\n",
- (unsigned int)gid, sid_string_static(psid)));
-
- return psid;
- }
- else
- return NULL;
- }
-
- sid_copy( psid, &group.sid );
-
- DEBUG(10,("local_gid_to_sid: gid (%d) -> SID %s.\n",
- (unsigned int)gid, sid_string_static(psid)));
-
- return psid;
-}
-
-/****************************************************************************
- Convert a SID to gid - locally.
-****************************************************************************/
-
-BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_type)
-{
- uint32 rid;
- GROUP_MAP group;
- BOOL ret;
-
- *name_type = SID_NAME_UNKNOWN;
-
- /* This call can enumerate group mappings for foreign sids as well.
- So don't check for a match against our domain SID */
-
- /* we don't need to disable winbindd since the gid is stored in
- the GROUP_MAP object */
-
- become_root();
- ret = pdb_getgrsid(&group, *psid);
- unbecome_root();
-
- if ( !ret ) {
-
- /* Fallback to algorithmic rid mapping if enabled */
-
- if ( lp_enable_rid_algorithm() ) {
-
- if (!sid_check_is_in_our_domain(psid) ) {
- DEBUG(5,("local_sid_to_gid: RID algorithm only supported for our domain (%s is not)\n", sid_string_static(psid)));
- return False;
- }
-
- if (!sid_peek_rid(psid, &rid)) {
- DEBUG(10,("local_sid_to_gid: invalid SID!\n"));
- return False;
- }
-
- DEBUG(10,("local_sid_to_gid: Fall back to algorithmic mapping\n"));
-
- if (algorithmic_pdb_rid_is_user(rid)) {
- DEBUG(3, ("local_sid_to_gid: SID %s is *NOT* a group\n", sid_string_static(psid)));
- return False;
- } else {
- *pgid = pdb_group_rid_to_gid(rid);
- DEBUG(10,("local_sid_to_gid: mapping: %s -> %u\n", sid_string_static(psid), (unsigned int)(*pgid)));
- return True;
- }
- }
-
- return False;
- }
-
- *pgid = group.gid;
- *name_type = group.sid_name_use;
-
- DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u)\n", sid_string_static(psid),
- (unsigned int)*pgid));
-
- return True;
+ return NT_STATUS_OK;
}
/**********************************************************************
@@ -2251,51 +2031,6 @@ BOOL pdb_copy_sam_account(const SAM_ACCOUNT *src, SAM_ACCOUNT **dst)
return result;
}
-/**********************************************************************
-**********************************************************************/
-
-static BOOL get_free_ugid_range(uint32 *low, uint32 *high)
-{
- uid_t u_low, u_high;
- gid_t g_low, g_high;
-
- if (!lp_idmap_uid(&u_low, &u_high) || !lp_idmap_gid(&g_low, &g_high)) {
- return False;
- }
-
- *low = (u_low < g_low) ? u_low : g_low;
- *high = (u_high < g_high) ? u_high : g_high;
-
- return True;
-}
-
-/******************************************************************
- Get the the non-algorithmic RID range if idmap range are defined
-******************************************************************/
-
-BOOL get_free_rid_range(uint32 *low, uint32 *high)
-{
- uint32 id_low, id_high;
-
- if (!lp_enable_rid_algorithm()) {
- *low = BASE_RID;
- *high = (uint32)-1;
- }
-
- if (!get_free_ugid_range(&id_low, &id_high)) {
- return False;
- }
-
- *low = algorithmic_pdb_uid_to_user_rid(id_low);
- if (algorithmic_pdb_user_rid_to_uid((uint32)-1) < id_high) {
- *high = (uint32)-1;
- } else {
- *high = algorithmic_pdb_uid_to_user_rid(id_high);
- }
-
- return True;
-}
-
/*********************************************************************
Update the bad password count checking the AP_RESET_COUNT_TIME
*********************************************************************/
diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c
index 783e9e23fa..71fb36e0d5 100644
--- a/source3/passdb/pdb_get_set.c
+++ b/source3/passdb/pdb_get_set.c
@@ -958,7 +958,8 @@ BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[NT_HASH_LEN], enum
data_blob_clear_free(&sampass->private_u.nt_pw);
if (pwd) {
- sampass->private_u.nt_pw = data_blob(pwd, NT_HASH_LEN);
+ sampass->private_u.nt_pw =
+ data_blob_talloc(sampass->mem_ctx, pwd, NT_HASH_LEN);
} else {
sampass->private_u.nt_pw = data_blob(NULL, 0);
}
@@ -978,7 +979,8 @@ BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[LM_HASH_LEN],
data_blob_clear_free(&sampass->private_u.lm_pw);
if (pwd) {
- sampass->private_u.lm_pw = data_blob(pwd, LM_HASH_LEN);
+ sampass->private_u.lm_pw =
+ data_blob_talloc(sampass->mem_ctx, pwd, LM_HASH_LEN);
} else {
sampass->private_u.lm_pw = data_blob(NULL, 0);
}
@@ -1093,8 +1095,10 @@ BOOL pdb_set_backend_private_data (SAM_ACCOUNT *sampass, void *private_data,
if (!sampass)
return False;
- if (sampass->private_u.backend_private_data && sampass->private_u.backend_private_data_free_fn) {
- sampass->private_u.backend_private_data_free_fn(&sampass->private_u.backend_private_data);
+ if (sampass->private_u.backend_private_data &&
+ sampass->private_u.backend_private_data_free_fn) {
+ sampass->private_u.backend_private_data_free_fn(
+ &sampass->private_u.backend_private_data);
}
sampass->private_u.backend_private_data = private_data;
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c
index 4808af3908..d8afff2111 100644
--- a/source3/passdb/pdb_interface.c
+++ b/source3/passdb/pdb_interface.c
@@ -36,7 +36,10 @@ static void lazy_initialize_passdb(void)
}
static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name);
-
+static BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid,
+ const char **name,
+ enum SID_NAME_USE *psid_name_use,
+ union unid_t *unix_id);
/*******************************************************************
Clean up uninitialised passwords. The only way to tell
that these values are not 'real' is that they do not
@@ -526,9 +529,10 @@ static NTSTATUS context_enum_group_members(struct pdb_context *context,
}
static NTSTATUS context_enum_group_memberships(struct pdb_context *context,
- const char *username,
- gid_t primary_gid,
- DOM_SID **pp_sids, gid_t **pp_gids,
+ TALLOC_CTX *mem_ctx,
+ SAM_ACCOUNT *user,
+ DOM_SID **pp_sids,
+ gid_t **pp_gids,
size_t *p_num_groups)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
@@ -539,8 +543,8 @@ static NTSTATUS context_enum_group_memberships(struct pdb_context *context,
}
return context->pdb_methods->
- enum_group_memberships(context->pdb_methods, username,
- primary_gid, pp_sids, pp_gids, p_num_groups);
+ enum_group_memberships(context->pdb_methods, mem_ctx, user,
+ pp_sids, pp_gids, p_num_groups);
}
static NTSTATUS context_find_alias(struct pdb_context *context,
@@ -757,6 +761,63 @@ static NTSTATUS context_get_seq_num(struct pdb_context *context, time_t *seq_num
return context->pdb_methods->get_seq_num(context->pdb_methods, seq_num);
}
+
+static BOOL context_uid_to_rid(struct pdb_context *context, uid_t uid,
+ uint32 *rid)
+{
+ if ((context == NULL) || (context->pdb_methods == NULL)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_methods->uid_to_rid(context->pdb_methods, uid,
+ rid);
+}
+
+static BOOL context_gid_to_sid(struct pdb_context *context, gid_t gid,
+ DOM_SID *sid)
+{
+ if ((context == NULL) || (context->pdb_methods == NULL)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_methods->gid_to_sid(context->pdb_methods, gid,
+ sid);
+}
+
+static BOOL context_sid_to_id(struct pdb_context *context,
+ const DOM_SID *sid,
+ union unid_t *id, enum SID_NAME_USE *type)
+{
+ if ((context == NULL) || (context->pdb_methods == NULL)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_methods->sid_to_id(context->pdb_methods, sid,
+ id, type);
+}
+
+static BOOL context_rid_algorithm(struct pdb_context *context)
+{
+ if ((context == NULL) || (context->pdb_methods == NULL)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_methods->rid_algorithm(context->pdb_methods);
+}
+
+static BOOL context_new_rid(struct pdb_context *context, uint32 *rid)
+{
+ if ((context == NULL) || (context->pdb_methods == NULL)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_methods->new_rid(context->pdb_methods, rid);
+}
/******************************************************************
Free and cleanup a pdb context, any associated data and anything
@@ -936,6 +997,13 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
(*context)->pdb_search_groups = context_search_groups;
(*context)->pdb_search_aliases = context_search_aliases;
+ (*context)->pdb_uid_to_rid = context_uid_to_rid;
+ (*context)->pdb_gid_to_sid = context_gid_to_sid;
+ (*context)->pdb_sid_to_id = context_sid_to_id;
+
+ (*context)->pdb_rid_algorithm = context_rid_algorithm;
+ (*context)->pdb_new_rid = context_new_rid;
+
(*context)->free_fn = free_pdb_context;
return NT_STATUS_OK;
@@ -1126,12 +1194,12 @@ BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct)
return NT_STATUS_IS_OK(pdb_context->pdb_add_sam_account(pdb_context, sam_acct));
}
-BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct)
+NTSTATUS pdb_update_sam_account(SAM_ACCOUNT *sam_acct)
{
struct pdb_context *pdb_context = pdb_get_static_context(False);
if (!pdb_context) {
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
if (sam_account_cache != NULL) {
@@ -1139,7 +1207,7 @@ BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct)
sam_account_cache = NULL;
}
- return NT_STATUS_IS_OK(pdb_context->pdb_update_sam_account(pdb_context, sam_acct));
+ return pdb_context->pdb_update_sam_account(pdb_context, sam_acct);
}
BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct)
@@ -1221,28 +1289,26 @@ BOOL pdb_getgrnam(GROUP_MAP *map, const char *name)
pdb_getgrnam(pdb_context, map, name));
}
-BOOL pdb_add_group_mapping_entry(GROUP_MAP *map)
+NTSTATUS pdb_add_group_mapping_entry(GROUP_MAP *map)
{
struct pdb_context *pdb_context = pdb_get_static_context(False);
if (!pdb_context) {
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_add_group_mapping_entry(pdb_context, map));
+ return pdb_context->pdb_add_group_mapping_entry(pdb_context, map);
}
-BOOL pdb_update_group_mapping_entry(GROUP_MAP *map)
+NTSTATUS pdb_update_group_mapping_entry(GROUP_MAP *map)
{
struct pdb_context *pdb_context = pdb_get_static_context(False);
if (!pdb_context) {
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_update_group_mapping_entry(pdb_context, map));
+ return pdb_context->pdb_update_group_mapping_entry(pdb_context, map);
}
BOOL pdb_delete_group_mapping_entry(DOM_SID sid)
@@ -1286,7 +1352,7 @@ NTSTATUS pdb_enum_group_members(TALLOC_CTX *mem_ctx,
pp_member_rids, p_num_members);
}
-NTSTATUS pdb_enum_group_memberships(const char *username, gid_t primary_gid,
+NTSTATUS pdb_enum_group_memberships(TALLOC_CTX *mem_ctx, SAM_ACCOUNT *user,
DOM_SID **pp_sids, gid_t **pp_gids,
size_t *p_num_groups)
{
@@ -1296,9 +1362,9 @@ NTSTATUS pdb_enum_group_memberships(const char *username, gid_t primary_gid,
return NT_STATUS_UNSUCCESSFUL;
}
- return pdb_context->pdb_enum_group_memberships(pdb_context, username,
- primary_gid, pp_sids, pp_gids,
- p_num_groups);
+ return pdb_context->pdb_enum_group_memberships(
+ pdb_context, mem_ctx, user,
+ pp_sids, pp_gids, p_num_groups);
}
BOOL pdb_find_alias(const char *name, DOM_SID *sid)
@@ -1361,60 +1427,58 @@ BOOL pdb_set_aliasinfo(const DOM_SID *sid, struct acct_info *info)
info));
}
-BOOL pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
+NTSTATUS pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
{
struct pdb_context *pdb_context = pdb_get_static_context(False);
if (!pdb_context) {
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_add_aliasmem(pdb_context, alias, member));
+ return pdb_context->pdb_add_aliasmem(pdb_context, alias, member);
}
-BOOL pdb_del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
+NTSTATUS pdb_del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
{
struct pdb_context *pdb_context = pdb_get_static_context(False);
if (!pdb_context) {
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_del_aliasmem(pdb_context, alias, member));
+ return pdb_context->pdb_del_aliasmem(pdb_context, alias, member);
}
-BOOL pdb_enum_aliasmem(const DOM_SID *alias,
- DOM_SID **pp_members, size_t *p_num_members)
+NTSTATUS pdb_enum_aliasmem(const DOM_SID *alias,
+ DOM_SID **pp_members, size_t *p_num_members)
{
struct pdb_context *pdb_context = pdb_get_static_context(False);
if (!pdb_context) {
- return False;
+ return NT_STATUS_UNSUCCESSFUL;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_enum_aliasmem(pdb_context, alias,
- pp_members, p_num_members));
+ return pdb_context->pdb_enum_aliasmem(pdb_context, alias,
+ pp_members, p_num_members);
}
-BOOL pdb_enum_alias_memberships(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
- const DOM_SID *members, size_t num_members,
- uint32 **pp_alias_rids, size_t *p_num_alias_rids)
+NTSTATUS pdb_enum_alias_memberships(TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ const DOM_SID *members, size_t num_members,
+ uint32 **pp_alias_rids,
+ size_t *p_num_alias_rids)
{
struct pdb_context *pdb_context = pdb_get_static_context(False);
if (!pdb_context) {
- return False;
+ return NT_STATUS_NOT_IMPLEMENTED;
}
- return NT_STATUS_IS_OK(pdb_context->
- pdb_enum_alias_memberships(pdb_context, mem_ctx,
- domain_sid,
- members, num_members,
- pp_alias_rids,
- p_num_alias_rids));
+ return pdb_context->pdb_enum_alias_memberships(pdb_context, mem_ctx,
+ domain_sid,
+ members, num_members,
+ pp_alias_rids,
+ p_num_alias_rids);
}
NTSTATUS pdb_lookup_rids(const DOM_SID *domain_sid,
@@ -1484,6 +1548,78 @@ BOOL pdb_get_seq_num(time_t *seq_num)
return NT_STATUS_IS_OK(pdb_context->
pdb_get_seq_num(pdb_context, seq_num));
}
+
+BOOL pdb_uid_to_rid(uid_t uid, uint32 *rid)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return pdb_context->pdb_uid_to_rid(pdb_context, uid, rid);
+}
+
+BOOL pdb_gid_to_sid(gid_t gid, DOM_SID *sid)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return pdb_context->pdb_gid_to_sid(pdb_context, gid, sid);
+}
+
+BOOL pdb_sid_to_id(const DOM_SID *sid, union unid_t *id,
+ enum SID_NAME_USE *type)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return pdb_context->pdb_sid_to_id(pdb_context, sid, id, type);
+}
+
+BOOL pdb_rid_algorithm(void)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return pdb_context->pdb_rid_algorithm(pdb_context);
+}
+
+BOOL pdb_new_rid(uint32 *rid)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ if (pdb_rid_algorithm()) {
+ DEBUG(0, ("Trying to allocate a RID when algorithmic RIDs "
+ "are active\n"));
+ return False;
+ }
+
+ if (algorithmic_rid_base() != BASE_RID) {
+ DEBUG(0, ("'algorithmic rid base' is set but a passdb backend "
+ "without algorithmic RIDs is chosen.\n"));
+ DEBUGADD(0, ("Please map all used groups using 'net groupmap "
+ "add', set the maximum used RID using\n"));
+ DEBUGADD(0, ("'net setmaxrid' and remove the parameter\n"));
+ return False;
+ }
+
+ return pdb_context->pdb_new_rid(pdb_context, rid);
+}
+
/***************************************************************
Initialize the static context (at smbd startup etc).
@@ -1567,6 +1703,117 @@ static NTSTATUS pdb_default_get_seq_num(struct pdb_methods *methods, time_t *seq
return NT_STATUS_OK;
}
+static BOOL pdb_default_uid_to_rid(struct pdb_methods *methods, uid_t uid,
+ uint32 *rid)
+{
+ SAM_ACCOUNT *sampw = NULL;
+ struct passwd *unix_pw;
+ BOOL ret;
+
+ unix_pw = sys_getpwuid( uid );
+
+ if ( !unix_pw ) {
+ DEBUG(4,("pdb_default_uid_to_rid: host has no idea of uid "
+ "%lu\n", (unsigned long)uid));
+ return False;
+ }
+
+ if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) {
+ DEBUG(0,("pdb_default_uid_to_rid: failed to allocate "
+ "SAM_ACCOUNT object\n"));
+ return False;
+ }
+
+ become_root();
+ ret = NT_STATUS_IS_OK(
+ methods->getsampwnam(methods, sampw, unix_pw->pw_name ));
+ unbecome_root();
+
+ if (!ret) {
+ DEBUG(5, ("pdb_default_uid_to_rid: Did not find user "
+ "%s (%d)\n", unix_pw->pw_name, uid));
+ pdb_free_sam(&sampw);
+ return False;
+ }
+
+ ret = sid_peek_check_rid(get_global_sam_sid(),
+ pdb_get_user_sid(sampw), rid);
+
+ if (!ret) {
+ DEBUG(1, ("Could not peek rid out of sid %s\n",
+ sid_string_static(pdb_get_user_sid(sampw))));
+ }
+
+ pdb_free_sam(&sampw);
+ return ret;
+}
+
+static BOOL pdb_default_gid_to_sid(struct pdb_methods *methods, gid_t gid,
+ DOM_SID *sid)
+{
+ GROUP_MAP map;
+
+ if (!NT_STATUS_IS_OK(methods->getgrgid(methods, &map, gid))) {
+ return False;
+ }
+
+ sid_copy(sid, &map.sid);
+ return True;
+}
+
+static BOOL pdb_default_sid_to_id(struct pdb_methods *methods,
+ const DOM_SID *sid,
+ union unid_t *id, enum SID_NAME_USE *type)
+{
+ TALLOC_CTX *mem_ctx;
+ BOOL ret = False;
+ const char *name;
+ uint32 rid;
+
+ mem_ctx = talloc_new(NULL);
+
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return False;
+ }
+
+ if (sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) {
+ /* Here we might have users as well as groups and aliases */
+ ret = lookup_global_sam_rid(mem_ctx, rid, &name, type, id);
+ goto done;
+ }
+
+ if (sid_peek_check_rid(&global_sid_Builtin, sid, &rid)) {
+ /* Here we only have aliases */
+ GROUP_MAP map;
+ if (!NT_STATUS_IS_OK(methods->getgrsid(methods, &map, *sid))) {
+ DEBUG(10, ("Could not find map for sid %s\n",
+ sid_string_static(sid)));
+ goto done;
+ }
+ if ((map.sid_name_use != SID_NAME_ALIAS) &&
+ (map.sid_name_use != SID_NAME_WKN_GRP)) {
+ DEBUG(10, ("Map for sid %s is a %s, expected an "
+ "alias\n", sid_string_static(sid),
+ sid_type_lookup(map.sid_name_use)));
+ goto done;
+ }
+
+ id->gid = map.gid;
+ *type = SID_NAME_ALIAS;
+ ret = True;
+ goto done;
+ }
+
+ DEBUG(5, ("Sid %s is neither ours nor builtin, don't know it\n",
+ sid_string_static(sid)));
+
+ done:
+
+ talloc_free(mem_ctx);
+ return ret;
+}
+
static void add_uid_to_array_unique(TALLOC_CTX *mem_ctx,
uid_t uid, uid_t **pp_uids, size_t *p_num)
{
@@ -1644,7 +1891,7 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
*pp_member_rids = NULL;
*p_num_members = 0;
- if (!NT_STATUS_IS_OK(sid_to_gid(group, &gid)))
+ if (!sid_to_gid(group, &gid))
return NT_STATUS_NO_SUCH_GROUP;
if(!get_memberuids(mem_ctx, gid, &uids, &num_uids))
@@ -1658,10 +1905,7 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
for (i=0; i<num_uids; i++) {
DOM_SID sid;
- if (!NT_STATUS_IS_OK(uid_to_sid(&sid, uids[i]))) {
- DEBUG(1, ("Could not map member uid to SID\n"));
- continue;
- }
+ uid_to_sid(&sid, uids[i]);
if (!sid_check_is_in_our_domain(&sid)) {
DEBUG(1, ("Inconsistent SAM -- group member uid not "
@@ -1676,6 +1920,92 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
return NT_STATUS_OK;
}
+/*******************************************************************
+ Look up a rid in the SAM we're responsible for (i.e. passdb)
+ ********************************************************************/
+
+static BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid,
+ const char **name,
+ enum SID_NAME_USE *psid_name_use,
+ union unid_t *unix_id)
+{
+ SAM_ACCOUNT *sam_account = NULL;
+ GROUP_MAP map;
+ BOOL ret;
+ DOM_SID sid;
+
+ *psid_name_use = SID_NAME_UNKNOWN;
+
+ DEBUG(5,("lookup_global_sam_rid: looking up RID %u.\n",
+ (unsigned int)rid));
+
+ sid_copy(&sid, get_global_sam_sid());
+ sid_append_rid(&sid, rid);
+
+ /* see if the passdb can help us with the name of the user */
+ if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
+ return False;
+ }
+
+ /* BEING ROOT BLLOCK */
+ become_root();
+ if (pdb_getsampwsid(sam_account, &sid)) {
+ struct passwd *pw;
+
+ unbecome_root(); /* -----> EXIT BECOME_ROOT() */
+ *name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
+ *psid_name_use = SID_NAME_USER;
+
+ pdb_free_sam(&sam_account);
+
+ if (unix_id == NULL) {
+ return True;
+ }
+
+ pw = Get_Pwnam(*name);
+ if (pw == NULL) {
+ return False;
+ }
+ unix_id->uid = pw->pw_uid;
+ return True;
+ }
+ pdb_free_sam(&sam_account);
+
+ ret = pdb_getgrsid(&map, sid);
+ unbecome_root();
+ /* END BECOME_ROOT BLOCK */
+
+ if ( ret ) {
+ if (map.gid!=(gid_t)-1) {
+ DEBUG(5,("lookup_global_sam_rid: mapped group %s to "
+ "gid %u\n", map.nt_name,
+ (unsigned int)map.gid));
+ } else {
+ DEBUG(5,("lookup_global_sam_rid: mapped group %s to "
+ "no unix gid. Returning name.\n",
+ map.nt_name));
+ }
+
+ *name = talloc_strdup(mem_ctx, map.nt_name);
+ *psid_name_use = map.sid_name_use;
+
+ if (unix_id == NULL) {
+ return True;
+ }
+
+ if (map.gid == (gid_t)-1) {
+ DEBUG(5, ("Can't find a unix id for an unmapped "
+ "group\n"));
+ return False;
+ }
+
+ unix_id->gid = map.gid;
+ return True;
+ }
+
+ return False;
+}
+
NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods,
const DOM_SID *domain_sid,
int num_rids,
@@ -1715,7 +2045,8 @@ NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods,
for (i = 0; i < num_rids; i++) {
const char *name;
- if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i])) {
+ if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i],
+ NULL)) {
names[i] = name;
DEBUG(5,("lookup_rids: %s:%d\n", names[i], attrs[i]));
have_mapped = True;
@@ -1772,11 +2103,9 @@ NTSTATUS pdb_default_lookup_names(struct pdb_methods *methods,
}
for (i = 0; i < num_names; i++) {
- const char *name;
-
- if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i])) {
- names[i] = name;
- DEBUG(5,("lookup_rids: %s:%d\n", names[i], attrs[i]));
+ if (lookup_global_sam_name(names[i], 0, &rids[i], &attrs[i])) {
+ DEBUG(5,("lookup_names: %s-> %d:%d\n", names[i],
+ rids[i], attrs[i]));
have_mapped = True;
} else {
have_unmapped = True;
@@ -2157,6 +2486,9 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
(*methods)->get_account_policy = pdb_default_get_account_policy;
(*methods)->set_account_policy = pdb_default_set_account_policy;
(*methods)->get_seq_num = pdb_default_get_seq_num;
+ (*methods)->uid_to_rid = pdb_default_uid_to_rid;
+ (*methods)->gid_to_sid = pdb_default_gid_to_sid;
+ (*methods)->sid_to_id = pdb_default_sid_to_id;
(*methods)->search_users = pdb_default_search_users;
(*methods)->search_groups = pdb_default_search_groups;
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index b35ce18eee..a21e976803 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -84,13 +84,12 @@
#include "smbldap.h"
/**********************************************************************
- Free a LDAPMessage (one is stored on the SAM_ACCOUNT).
+ Simple helper function to make stuff better readable
**********************************************************************/
-
-void private_data_free_fn(void **result)
+
+static LDAP *priv2ld(struct ldapsam_privates *priv)
{
- ldap_msgfree(*result);
- *result = NULL;
+ return priv->smbldap_state->ldap_struct;
}
/**********************************************************************
@@ -117,14 +116,14 @@ static const char* get_userattr_key2string( int schema_ver, int key )
Return the list of attribute names given a user schema version.
**********************************************************************/
-const char** get_userattr_list( int schema_ver )
+const char** get_userattr_list( TALLOC_CTX *mem_ctx, int schema_ver )
{
switch ( schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
- return get_attr_list( attrib_map_v22 );
+ return get_attr_list( mem_ctx, attrib_map_v22 );
case SCHEMAVER_SAMBASAMACCOUNT:
- return get_attr_list( attrib_map_v30 );
+ return get_attr_list( mem_ctx, attrib_map_v30 );
default:
DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
break;
@@ -137,14 +136,17 @@ const char** get_userattr_list( int schema_ver )
Return the list of attribute names to delete given a user schema version.
**************************************************************************/
-static const char** get_userattr_delete_list( int schema_ver )
+static const char** get_userattr_delete_list( TALLOC_CTX *mem_ctx,
+ int schema_ver )
{
switch ( schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
- return get_attr_list( attrib_map_to_delete_v22 );
+ return get_attr_list( mem_ctx,
+ attrib_map_to_delete_v22 );
case SCHEMAVER_SAMBASAMACCOUNT:
- return get_attr_list( attrib_map_to_delete_v30 );
+ return get_attr_list( mem_ctx,
+ attrib_map_to_delete_v30 );
default:
DEBUG(0,("get_userattr_delete_list: unknown schema version specified!\n"));
break;
@@ -250,13 +252,6 @@ static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_
LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &msg);
if (rc != LDAP_SUCCESS) {
-
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct,
- LDAP_OPT_ERROR_STRING, &ld_error);
- DEBUG(0,("ldapsam_get_seq_num: Failed search for suffix: %s, error: %s (%s)\n",
- suffix,ldap_err2string(rc), ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
goto done;
}
@@ -399,58 +394,37 @@ static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
object found in search_result depending on lp_ldap_delete_dn
******************************************************************/
-static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
- LDAPMessage *result,
- const char *objectclass,
- const char **attrs)
+static int ldapsam_delete_entry(struct ldapsam_privates *priv,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *entry,
+ const char *objectclass,
+ const char **attrs)
{
- int rc;
- LDAPMessage *entry = NULL;
LDAPMod **mods = NULL;
- char *name, *dn;
+ char *name;
+ const char *dn;
BerElement *ptr = NULL;
- rc = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
-
- if (rc != 1) {
- DEBUG(0, ("ldapsam_delete_entry: Entry must exist exactly once!\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
- dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
- if (!dn) {
- return NT_STATUS_UNSUCCESSFUL;
+ dn = smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry);
+ if (dn == NULL) {
+ return LDAP_NO_MEMORY;
}
if (lp_ldap_delete_dn()) {
- NTSTATUS ret = NT_STATUS_OK;
- rc = smbldap_delete(ldap_state->smbldap_state, dn);
-
- if (rc != LDAP_SUCCESS) {
- DEBUG(0, ("ldapsam_delete_entry: Could not delete object %s\n", dn));
- ret = NT_STATUS_UNSUCCESSFUL;
- }
- SAFE_FREE(dn);
- return ret;
+ return smbldap_delete(priv->smbldap_state, dn);
}
/* Ok, delete only the SAM attributes */
- for (name = ldap_first_attribute(ldap_state->smbldap_state->ldap_struct, entry, &ptr);
+ for (name = ldap_first_attribute(priv2ld(priv), entry, &ptr);
name != NULL;
- name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr)) {
+ name = ldap_next_attribute(priv2ld(priv), entry, ptr)) {
const char **attrib;
/* We are only allowed to delete the attributes that
really exist. */
for (attrib = attrs; *attrib != NULL; attrib++) {
- /* Don't delete LDAP_ATTR_MOD_TIMESTAMP attribute. */
- if (strequal(*attrib, get_userattr_key2string(ldap_state->schema_ver,
- LDAP_ATTR_MOD_TIMESTAMP))) {
- continue;
- }
if (strequal(*attrib, name)) {
DEBUG(10, ("ldapsam_delete_entry: deleting "
"attribute %s\n", name));
@@ -458,33 +432,17 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
NULL);
}
}
-
ldap_memfree(name);
}
-
+
if (ptr != NULL) {
ber_free(ptr, 0);
}
smbldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
-
- rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
- ldap_mods_free(mods, True);
-
- if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
-
- DEBUG(0, ("ldapsam_delete_entry: Could not delete attributes for %s, error: %s (%s)\n",
- dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
- SAFE_FREE(dn);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- SAFE_FREE(dn);
- return NT_STATUS_OK;
+ talloc_autofree_ldapmod(mem_ctx, mods);
+
+ return smbldap_modify(priv->smbldap_state, dn, mods);
}
/* New Interface is being implemented here */
@@ -627,13 +585,16 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
return False;
}
- if (ldap_state->smbldap_state->ldap_struct == NULL) {
- DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->ldap_struct is NULL!\n"));
+ if (priv2ld(ldap_state) == NULL) {
+ DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->"
+ "ldap_struct is NULL!\n"));
return False;
}
- if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) {
- DEBUG(1, ("init_sam_from_ldap: No uid attribute found for this user!\n"));
+ if (!smbldap_get_single_pstring(priv2ld(ldap_state), entry, "uid",
+ username)) {
+ DEBUG(1, ("init_sam_from_ldap: No uid attribute found for "
+ "this user!\n"));
return False;
}
@@ -992,6 +953,15 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
ZERO_STRUCT(hours);
}
+ if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+ if (smbldap_get_single_pstring(priv2ld(ldap_state), entry,
+ "uidNumber", temp)) {
+ /* We've got a uid, feed the cache */
+ uid_t uid = strtoul(temp, NULL, 10);
+ store_uid_sid_cache(pdb_get_user_sid(sampass), uid);
+ }
+ }
+
/* check the timestamp of the cache vs ldap entry */
if (!(ldap_entry_time = ldapsam_get_entry_timestamp(ldap_state,
entry)))
@@ -1380,10 +1350,10 @@ static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update,
DEBUG(10,("ldapsam_setsampwent: LDAP Query for acb_mask 0x%x will use suffix %s\n",
acb_mask, suffix));
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
rc = smbldap_search(ldap_state->smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter,
attr_list, 0, &ldap_state->result);
- free_attr_list( attr_list );
+ talloc_free( attr_list );
if (rc != LDAP_SUCCESS) {
DEBUG(0, ("ldapsam_setsampwent: LDAP search failed: %s\n", ldap_err2string(rc)));
@@ -1421,10 +1391,12 @@ static void ldapsam_endsampwent(struct pdb_methods *my_methods)
Get the next entry in the LDAP password database.
*********************************************************************/
-static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
+static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods,
+ SAM_ACCOUNT *user)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)my_methods->private_data;
BOOL bret = False;
while (!bret) {
@@ -1434,14 +1406,15 @@ static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT
ldap_state->index++;
bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
- ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
- ldap_state->entry);
+ ldap_state->entry = ldap_next_entry(priv2ld(ldap_state),
+ ldap_state->entry);
}
return NT_STATUS_OK;
}
-static void append_attr(const char ***attr_list, const char *new_attr)
+static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list,
+ const char *new_attr)
{
int i;
@@ -1453,9 +1426,10 @@ static void append_attr(const char ***attr_list, const char *new_attr)
;
}
- (*attr_list) = SMB_REALLOC_ARRAY((*attr_list), const char *, i+2);
+ (*attr_list) = TALLOC_REALLOC_ARRAY(mem_ctx, (*attr_list),
+ const char *, i+2);
SMB_ASSERT((*attr_list) != NULL);
- (*attr_list)[i] = SMB_STRDUP(new_attr);
+ (*attr_list)[i] = talloc_strdup((*attr_list), new_attr);
(*attr_list)[i+1] = NULL;
}
@@ -1473,10 +1447,14 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT
const char ** attr_list;
int rc;
- attr_list = get_userattr_list( ldap_state->schema_ver );
- append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP));
- rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
- free_attr_list( attr_list );
+ attr_list = get_userattr_list( user->mem_ctx, ldap_state->schema_ver );
+ append_attr(user->mem_ctx, &attr_list,
+ get_userattr_key2string(ldap_state->schema_ver,
+ LDAP_ATTR_MOD_TIMESTAMP));
+ append_attr(user->mem_ctx, &attr_list, "uidNumber");
+ rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result,
+ attr_list);
+ talloc_free( attr_list );
if ( rc != LDAP_SUCCESS )
return NT_STATUS_NO_SUCH_USER;
@@ -1500,9 +1478,9 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_USER;
}
- pdb_set_backend_private_data(user, result,
- private_data_free_fn,
+ pdb_set_backend_private_data(user, result, NULL,
my_methods, PDB_CHANGED);
+ talloc_autofree_ldapmsg(user->mem_ctx, result);
ret = NT_STATUS_OK;
} else {
ldap_msgfree(result);
@@ -1518,24 +1496,37 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state,
uint32 rid;
switch ( ldap_state->schema_ver ) {
- case SCHEMAVER_SAMBASAMACCOUNT:
- attr_list = get_userattr_list(ldap_state->schema_ver);
- append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP));
- rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list);
- free_attr_list( attr_list );
+ case SCHEMAVER_SAMBASAMACCOUNT: {
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return LDAP_NO_MEMORY;
+ }
+
+ attr_list = get_userattr_list(tmp_ctx,
+ ldap_state->schema_ver);
+ append_attr(tmp_ctx, &attr_list,
+ get_userattr_key2string(
+ ldap_state->schema_ver,
+ LDAP_ATTR_MOD_TIMESTAMP));
+ append_attr(tmp_ctx, &attr_list, "uidNumber");
+ rc = ldapsam_search_suffix_by_sid(ldap_state, sid,
+ result, attr_list);
+ talloc_free(tmp_ctx);
if ( rc != LDAP_SUCCESS )
return rc;
break;
+ }
case SCHEMAVER_SAMBAACCOUNT:
if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) {
return rc;
}
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL,
+ ldap_state->schema_ver);
rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list );
- free_attr_list( attr_list );
+ talloc_free( attr_list );
if ( rc != LDAP_SUCCESS )
return rc;
@@ -1588,9 +1579,9 @@ static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT
return NT_STATUS_NO_SUCH_USER;
}
- pdb_set_backend_private_data(user, result,
- private_data_free_fn,
+ pdb_set_backend_private_data(user, result, NULL,
my_methods, PDB_CHANGED);
+ talloc_autofree_ldapmsg(user->mem_ctx, result);
return NT_STATUS_OK;
}
@@ -1639,14 +1630,6 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
}
if (rc!=LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(1, ("ldapsam_modify_entry: Failed to %s user dn= %s with: %s\n\t%s\n",
- ldap_op == LDAP_MOD_ADD ? "add" : "modify",
- dn, ldap_err2string(rc),
- ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
return NT_STATUS_UNSUCCESSFUL;
}
}
@@ -1747,15 +1730,17 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
Delete entry from LDAP for username.
*********************************************************************/
-static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
+static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods,
+ SAM_ACCOUNT * sam_acct)
{
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ struct ldapsam_privates *priv =
+ (struct ldapsam_privates *)my_methods->private_data;
const char *sname;
int rc;
- LDAPMessage *result = NULL;
- NTSTATUS ret;
+ LDAPMessage *msg, *entry;
+ NTSTATUS result = NT_STATUS_NO_MEMORY;
const char **attr_list;
- fstring objclass;
+ TALLOC_CTX *mem_ctx;
if (!sam_acct) {
DEBUG(0, ("ldapsam_delete_sam_account: sam_acct was NULL!\n"));
@@ -1764,35 +1749,42 @@ static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_A
sname = pdb_get_username(sam_acct);
- DEBUG (3, ("ldapsam_delete_sam_account: Deleting user %s from LDAP.\n", sname));
+ DEBUG(3, ("ldapsam_delete_sam_account: Deleting user %s from "
+ "LDAP.\n", sname));
- attr_list= get_userattr_delete_list( ldap_state->schema_ver );
- rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ goto done;
+ }
- if (rc != LDAP_SUCCESS) {
- free_attr_list( attr_list );
- return NT_STATUS_NO_SUCH_USER;
+ attr_list = get_userattr_delete_list(mem_ctx, priv->schema_ver );
+ if (attr_list == NULL) {
+ goto done;
}
-
- switch ( ldap_state->schema_ver ) {
- case SCHEMAVER_SAMBASAMACCOUNT:
- fstrcpy( objclass, LDAP_OBJ_SAMBASAMACCOUNT );
- break;
-
- case SCHEMAVER_SAMBAACCOUNT:
- fstrcpy( objclass, LDAP_OBJ_SAMBAACCOUNT );
- break;
- default:
- fstrcpy( objclass, "UNKNOWN" );
- DEBUG(0,("ldapsam_delete_sam_account: Unknown schema version specified!\n"));
- break;
+
+ rc = ldapsam_search_suffix_by_name(priv, sname, &msg, attr_list);
+
+ if ((rc != LDAP_SUCCESS) ||
+ (ldap_count_entries(priv2ld(priv), msg) != 1) ||
+ ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
+ DEBUG(5, ("Could not find user %s\n", sname));
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
}
+
+ rc = ldapsam_delete_entry(
+ priv, mem_ctx, entry,
+ priv->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ?
+ LDAP_OBJ_SAMBASAMACCOUNT : LDAP_OBJ_SAMBAACCOUNT,
+ attr_list);
- ret = ldapsam_delete_entry(ldap_state, result, objclass, attr_list );
- ldap_msgfree(result);
- free_attr_list( attr_list );
+ result = (rc == LDAP_SUCCESS) ?
+ NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
- return ret;
+ done:
+ talloc_free(mem_ctx);
+ return result;
}
/**********************************************************************
@@ -1823,13 +1815,15 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A
result = pdb_get_backend_private_data(newpwd, my_methods);
if (!result) {
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list );
- free_attr_list( attr_list );
+ talloc_free( attr_list );
if (rc != LDAP_SUCCESS) {
return NT_STATUS_UNSUCCESSFUL;
}
- pdb_set_backend_private_data(newpwd, result, private_data_free_fn, my_methods, PDB_CHANGED);
+ pdb_set_backend_private_data(newpwd, result, NULL,
+ my_methods, PDB_CHANGED);
+ talloc_autofree_ldapmsg(newpwd->mem_ctx, result);
}
if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
@@ -1866,12 +1860,6 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A
SAFE_FREE(dn);
if (!NT_STATUS_IS_OK(ret)) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(0,("ldapsam_update_sam_account: failed to modify user with uid = %s, error: %s (%s)\n",
- pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
- SAFE_FREE(ld_error);
return ret;
}
@@ -1966,12 +1954,12 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
}
/* free this list after the second search or in case we exit on failure */
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
if (rc != LDAP_SUCCESS) {
- free_attr_list( attr_list );
+ talloc_free( attr_list );
return NT_STATUS_UNSUCCESSFUL;
}
@@ -1979,7 +1967,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
DEBUG(0,("ldapsam_add_sam_account: User '%s' already in the base, with samba attributes\n",
username));
ldap_msgfree(result);
- free_attr_list( attr_list );
+ talloc_free( attr_list );
return NT_STATUS_UNSUCCESSFUL;
}
ldap_msgfree(result);
@@ -1992,7 +1980,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
DEBUG(0,("ldapsam_add_sam_account: SID '%s' already in the base, with samba attributes\n",
sid_to_string(sid_string, sid)));
- free_attr_list( attr_list );
+ talloc_free( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2011,7 +1999,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
rc = smbldap_search_suffix(ldap_state->smbldap_state,
filter, attr_list, &result);
if ( rc != LDAP_SUCCESS ) {
- free_attr_list( attr_list );
+ talloc_free( attr_list );
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2019,7 +2007,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
if (num_result > 1) {
DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
- free_attr_list( attr_list );
+ talloc_free( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2033,7 +2021,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
if (!tmp) {
- free_attr_list( attr_list );
+ talloc_free( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2059,7 +2047,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
filter, attr_list, &result);
if ( rc != LDAP_SUCCESS ) {
- free_attr_list( attr_list );
+ talloc_free( attr_list );
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2067,7 +2055,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
if (num_result > 1) {
DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
- free_attr_list( attr_list );
+ talloc_free( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2081,7 +2069,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
if (!tmp) {
- free_attr_list( attr_list );
+ talloc_free( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -2090,7 +2078,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
}
}
- free_attr_list( attr_list );
+ talloc_free( attr_list );
if (num_result == 0) {
/* Check if we need to add an entry */
@@ -2155,23 +2143,11 @@ static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
int rc;
const char **attr_list;
- attr_list = get_attr_list(groupmap_attr_list);
+ attr_list = get_attr_list(NULL, groupmap_attr_list);
rc = smbldap_search(ldap_state->smbldap_state,
lp_ldap_group_suffix (), scope,
filter, attr_list, 0, result);
- free_attr_list( attr_list );
-
- if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(0, ("ldapsam_search_one_group: "
- "Problem during the LDAP search: LDAP error: %s (%s)\n",
- ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
- DEBUGADD(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
- lp_ldap_group_suffix(), filter));
- SAFE_FREE(ld_error);
- }
+ talloc_free(attr_list);
return rc;
}
@@ -2245,39 +2221,10 @@ for gidNumber(%lu)\n",(unsigned long)map->gid));
}
fstrcpy(map->comment, temp);
- return True;
-}
-
-/**********************************************************************
- *********************************************************************/
-
-static BOOL init_ldap_from_group(LDAP *ldap_struct,
- LDAPMessage *existing,
- LDAPMod ***mods,
- const GROUP_MAP *map)
-{
- pstring tmp;
-
- if (mods == NULL || map == NULL) {
- DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
- return False;
+ if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+ store_gid_sid_cache(&map->sid, map->gid);
}
- *mods = NULL;
-
- sid_to_string(tmp, &map->sid);
-
- smbldap_make_mod(ldap_struct, existing, mods,
- get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp);
- pstr_sprintf(tmp, "%i", map->sid_name_use);
- smbldap_make_mod(ldap_struct, existing, mods,
- get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp);
-
- smbldap_make_mod(ldap_struct, existing, mods,
- get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), map->nt_name);
- smbldap_make_mod(ldap_struct, existing, mods,
- get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), map->comment);
-
return True;
}
@@ -2299,7 +2246,7 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
return NT_STATUS_NO_SUCH_GROUP;
}
- count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+ count = ldap_count_entries(priv2ld(ldap_state), result);
if (count < 1) {
DEBUG(4, ("ldapsam_getgroup: Did not find group\n"));
@@ -2308,13 +2255,13 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
}
if (count > 1) {
- DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: count=%d\n",
- filter, count));
+ DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: "
+ "count=%d\n", filter, count));
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_GROUP;
}
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
if (!entry) {
ldap_msgfree(result);
@@ -2322,8 +2269,8 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
}
if (!init_group_from_ldap(ldap_state, map, entry)) {
- DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for group filter %s\n",
- filter));
+ DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for "
+ "group filter %s\n", filter));
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_GROUP;
}
@@ -2458,11 +2405,6 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
char *tmp;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
- return pdb_default_enum_group_members(methods, mem_ctx, group,
- pp_member_rids,
- p_num_members);
-
*pp_member_rids = NULL;
*p_num_members = 0;
@@ -2618,9 +2560,10 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
}
static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
- const char *username,
- gid_t primary_gid,
- DOM_SID **pp_sids, gid_t **pp_gids,
+ TALLOC_CTX *mem_ctx,
+ SAM_ACCOUNT *user,
+ DOM_SID **pp_sids,
+ gid_t **pp_gids,
size_t *p_num_groups)
{
struct ldapsam_privates *ldap_state =
@@ -2634,23 +2577,24 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
LDAPMessage *entry;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
size_t num_sids, num_gids;
-
- if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
- return pdb_default_enum_group_memberships(methods, username,
- primary_gid, pp_sids,
- pp_gids, p_num_groups);
+ gid_t primary_gid;
*pp_sids = NULL;
num_sids = 0;
- escape_name = escape_ldap_string_alloc(username);
+ if (!sid_to_gid(pdb_get_group_sid(user), &primary_gid)) {
+ DEBUG(1, ("sid_to_gid failed for user's primary group\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ escape_name = escape_ldap_string_alloc(pdb_get_username(user));
if (escape_name == NULL)
return NT_STATUS_NO_MEMORY;
pstr_sprintf(filter, "(&(objectClass=posixGroup)"
"(|(memberUid=%s)(gidNumber=%d)))",
- username, primary_gid);
+ escape_name, primary_gid);
rc = smbldap_search(conn, lp_ldap_group_suffix(),
LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg);
@@ -2666,11 +2610,11 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
/* We need to add the primary group as the first gid/sid */
- add_gid_to_array_unique(NULL, primary_gid, pp_gids, &num_gids);
+ add_gid_to_array_unique(mem_ctx, primary_gid, pp_gids, &num_gids);
/* This sid will be replaced later */
- add_sid_to_array_unique(NULL, &global_sid_NULL, pp_sids, &num_sids);
+ add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids, &num_sids);
for (entry = ldap_first_entry(conn->ldap_struct, msg);
entry != NULL;
@@ -2702,13 +2646,16 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
if (gid == primary_gid) {
sid_copy(&(*pp_sids)[0], &sid);
} else {
- add_gid_to_array_unique(NULL, gid, pp_gids, &num_gids);
- add_sid_to_array_unique(NULL, &sid, pp_sids, &num_sids);
+ add_gid_to_array_unique(mem_ctx, gid, pp_gids,
+ &num_gids);
+ add_sid_to_array_unique(mem_ctx, &sid, pp_sids,
+ &num_sids);
}
}
if (sid_compare(&global_sid_NULL, &(*pp_sids)[0]) == 0) {
- DEBUG(3, ("primary group of [%s] not found\n", username));
+ DEBUG(3, ("primary group of [%s] not found\n",
+ pdb_get_username(user)));
goto done;
}
@@ -2726,143 +2673,203 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
}
/**********************************************************************
+ * Augment a posixGroup object with a sambaGroupMapping domgroup
*********************************************************************/
-static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
- gid_t gid,
- LDAPMessage **result)
+static NTSTATUS ldapsam_map_posixgroup(TALLOC_CTX *mem_ctx,
+ struct ldapsam_privates *ldap_state,
+ GROUP_MAP *map)
{
- pstring filter;
+ const char *filter, *dn;
+ LDAPMessage *msg, *entry;
+ LDAPMod **mods;
+ int rc;
- pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%lu))",
- LDAP_OBJ_POSIXGROUP, LDAP_OBJ_IDMAP_ENTRY,
- get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
- (unsigned long)gid);
+ filter = talloc_asprintf(mem_ctx,
+ "(&(objectClass=posixGroup)(gidNumber=%u))",
+ map->gid);
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- return ldapsam_search_one_group(ldap_state, filter, result);
-}
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
+ get_attr_list(mem_ctx, groupmap_attr_list),
+ &msg);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
-/**********************************************************************
- *********************************************************************/
+ if ((rc != LDAP_SUCCESS) ||
+ (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
+ ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
+ return NT_STATUS_NO_SUCH_GROUP;
+ }
+
+ dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
+ if (dn == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ mods = NULL;
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass",
+ "sambaGroupMapping");
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaSid",
+ sid_string_static(&map->sid));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaGroupType",
+ talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
+ map->nt_name);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
+ map->comment);
+ talloc_autofree_ldapmod(mem_ctx, mods);
+
+ rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
+ if (rc != LDAP_SUCCESS) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ return NT_STATUS_OK;
+}
static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
GROUP_MAP *map)
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
- LDAPMessage *result = NULL;
+ LDAPMessage *msg = NULL;
LDAPMod **mods = NULL;
- int count;
+ const char *attrs[] = { NULL };
+ char *filter;
- char *tmp;
- pstring dn;
- LDAPMessage *entry;
+ char *dn;
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS result;
- GROUP_MAP dummy;
+ DOM_SID sid;
int rc;
- if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
- map->gid))) {
- DEBUG(0, ("ldapsam_add_group_mapping_entry: Group %ld already exists in LDAP\n", (unsigned long)map->gid));
- return NT_STATUS_UNSUCCESSFUL;
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
}
- rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
- if (rc != LDAP_SUCCESS) {
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ filter = talloc_asprintf(mem_ctx, "(sambaSid=%s)",
+ sid_string_static(&map->sid));
+ if (filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
}
- count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+ rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, attrs, True, &msg);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
- if ( count == 0 ) {
- /* There's no posixGroup account, let's try to find an
- * appropriate idmap entry for aliases */
-
- pstring suffix;
- pstring filter;
- const char **attr_list;
-
- ldap_msgfree(result);
+ if ((rc == LDAP_SUCCESS) &&
+ (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) > 0)) {
- pstrcpy( suffix, lp_ldap_idmap_suffix() );
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%u))",
- LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_GIDNUMBER,
- map->gid);
-
- attr_list = get_attr_list( sidmap_attr_list );
- rc = smbldap_search(ldap_state->smbldap_state, suffix,
- LDAP_SCOPE_SUBTREE, filter, attr_list,
- 0, &result);
+ DEBUG(3, ("SID %s already present in LDAP, refusing to add "
+ "group mapping entry\n",
+ sid_string_static(&map->sid)));
+ result = NT_STATUS_GROUP_EXISTS;
+ goto done;
+ }
- free_attr_list(attr_list);
+ switch (map->sid_name_use) {
- if (rc != LDAP_SUCCESS) {
- DEBUG(3,("Failure looking up entry (%s)\n",
- ldap_err2string(rc) ));
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ case SID_NAME_DOM_GRP:
+ /* To map a domain group we need to have a posix group
+ to attach to. */
+ result = ldapsam_map_posixgroup(mem_ctx, ldap_state, map);
+ goto done;
+ break;
+
+ case SID_NAME_ALIAS:
+ if (!sid_check_is_in_our_domain(&map->sid)) {
+ DEBUG(3, ("Refusing to map sid %s as an alias, not "
+ "in our domain\n",
+ sid_string_static(&map->sid)));
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
}
- }
-
- count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
- if ( count == 0 ) {
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
- }
+ break;
+
+ case SID_NAME_WKN_GRP:
+ if (!sid_check_is_in_builtin(&map->sid)) {
+ DEBUG(3, ("Refusing to map sid %s as an alias, not "
+ "in builtin domain\n",
+ sid_string_static(&map->sid)));
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
+ }
+ break;
- if (count > 1) {
- DEBUG(2, ("ldapsam_add_group_mapping_entry: Group %lu must exist exactly once in LDAP\n",
- (unsigned long)map->gid));
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ default:
+ DEBUG(3, ("Got invalid use '%s' for mapping\n",
+ sid_type_lookup(map->sid_name_use)));
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
}
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
- tmp = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
- if (!tmp) {
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ /* Domain groups have been mapped in a separate routine, we have to
+ * create an alias now */
+
+ if (map->gid == -1) {
+ DEBUG(10, ("Refusing to map gid==-1\n"));
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
}
- pstrcpy(dn, tmp);
- SAFE_FREE(tmp);
- if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
- result, &mods, map)) {
- DEBUG(0, ("ldapsam_add_group_mapping_entry: init_ldap_from_group failed!\n"));
- ldap_mods_free(mods, True);
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ if (pdb_gid_to_sid(map->gid, &sid)) {
+ DEBUG(3, ("Gid %d is already mapped to SID %s, refusing to "
+ "add\n", map->gid, sid_string_static(&sid)));
+ result = NT_STATUS_GROUP_EXISTS;
+ goto done;
}
- ldap_msgfree(result);
+ /* Ok, enough checks done. It's still racy to go ahead now, but that's
+ * the best we can get out of LDAP. */
- if (mods == NULL) {
- DEBUG(0, ("ldapsam_add_group_mapping_entry: mods is empty\n"));
- return NT_STATUS_UNSUCCESSFUL;
+ dn = talloc_asprintf(mem_ctx, "sambaSid=%s,%s",
+ sid_string_static(&map->sid),
+ lp_ldap_group_suffix());
+ if (dn == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
}
- smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP );
+ mods = NULL;
- rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
- ldap_mods_free(mods, True);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
+ "sambaSidEntry");
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
+ "sambaGroupMapping");
- if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(0, ("ldapsam_add_group_mapping_entry: failed to add group %lu error: %s (%s)\n", (unsigned long)map->gid,
- ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
- SAFE_FREE(ld_error);
- return NT_STATUS_UNSUCCESSFUL;
- }
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaSid",
+ sid_string_static(&map->sid));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaGroupType",
+ talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "displayName",
+ map->nt_name);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "description",
+ map->comment);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "gidNumber",
+ talloc_asprintf(mem_ctx, "%u", map->gid));
+ talloc_autofree_ldapmod(mem_ctx, mods);
- DEBUG(2, ("ldapsam_add_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
- return NT_STATUS_OK;
+ rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
+
+ result = (rc == LDAP_SUCCESS) ?
+ NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+
+ done:
+ talloc_free(mem_ctx);
+ return result;
}
/**********************************************************************
+ * Update a group mapping entry. We're quite strict about what can be changed:
+ * Only the description and displayname may be changed. It simply does not
+ * make any sense to change the SID, gid or the type in a mapping.
*********************************************************************/
static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
@@ -2871,63 +2878,80 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
int rc;
- char *dn = NULL;
- LDAPMessage *result = NULL;
+ const char *filter, *dn;
+ LDAPMessage *msg = NULL;
LDAPMessage *entry = NULL;
LDAPMod **mods = NULL;
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS result;
- rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
- if (rc != LDAP_SUCCESS) {
- return NT_STATUS_UNSUCCESSFUL;
+ /* Make 100% sure that sid, gid and type are not changed by looking up
+ * exactly the values we're given in LDAP. */
+
+ filter = talloc_asprintf(mem_ctx, "(&(objectClass=sambaGroupMapping)"
+ "(sambaSid=%s)(gidNumber=%u)"
+ "(sambaGroupType=%d))",
+ sid_string_static(&map->sid), map->gid,
+ map->sid_name_use);
+ if (filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
}
- if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
- DEBUG(0, ("ldapsam_update_group_mapping_entry: No group to modify!\n"));
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
+ get_attr_list(mem_ctx, groupmap_attr_list),
+ &msg);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
+
+ if ((rc != LDAP_SUCCESS) ||
+ (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
+ ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
+ result = NT_STATUS_NO_SUCH_GROUP;
+ goto done;
}
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+ dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
- if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
- result, &mods, map)) {
- DEBUG(0, ("ldapsam_update_group_mapping_entry: init_ldap_from_group failed\n"));
- ldap_msgfree(result);
- if (mods != NULL)
- ldap_mods_free(mods,True);
- return NT_STATUS_UNSUCCESSFUL;
+ if (dn == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
}
+ mods = NULL;
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
+ map->nt_name);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
+ map->comment);
+ talloc_autofree_ldapmod(mem_ctx, mods);
+
if (mods == NULL) {
- DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: nothing to do\n"));
- ldap_msgfree(result);
- return NT_STATUS_OK;
+ DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: "
+ "nothing to do\n"));
+ result = NT_STATUS_OK;
+ goto done;
}
- dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
- if (!dn) {
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
- }
rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
- SAFE_FREE(dn);
-
- ldap_mods_free(mods, True);
- ldap_msgfree(result);
if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(0, ("ldapsam_update_group_mapping_entry: failed to modify group %lu error: %s (%s)\n", (unsigned long)map->gid,
- ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
- SAFE_FREE(ld_error);
- return NT_STATUS_UNSUCCESSFUL;
+ result = NT_STATUS_ACCESS_DENIED;
+ goto done;
}
- DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
- return NT_STATUS_OK;
+ DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified "
+ "group %lu in LDAP\n", (unsigned long)map->gid));
+
+ result = NT_STATUS_OK;
+
+ done:
+ talloc_free(mem_ctx);
+ return result;
}
/**********************************************************************
@@ -2936,53 +2960,103 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
DOM_SID sid)
{
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)methods->private_data;
- pstring sidstring, filter;
- LDAPMessage *result = NULL;
+ struct ldapsam_privates *priv =
+ (struct ldapsam_privates *)methods->private_data;
+ LDAPMessage *msg, *entry;
int rc;
- NTSTATUS ret;
- const char **attr_list;
+ NTSTATUS result;
+ TALLOC_CTX *mem_ctx;
+ char *filter;
- sid_to_string(sidstring, &sid);
-
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
- LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID, sidstring);
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
- rc = ldapsam_search_one_group(ldap_state, filter, &result);
+ filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%s))",
+ LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID,
+ sid_string_static(&sid));
+ if (filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ rc = smbldap_search_suffix(priv->smbldap_state, filter,
+ get_attr_list(mem_ctx, groupmap_attr_list),
+ &msg);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
- if (rc != LDAP_SUCCESS) {
- return NT_STATUS_NO_SUCH_GROUP;
+ if ((rc != LDAP_SUCCESS) ||
+ (ldap_count_entries(priv2ld(priv), msg) != 1) ||
+ ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
+ result = NT_STATUS_NO_SUCH_GROUP;
+ goto done;
+ }
+
+ rc = ldapsam_delete_entry(priv, mem_ctx, entry, LDAP_OBJ_GROUPMAP,
+ get_attr_list(mem_ctx,
+ groupmap_attr_list_to_delete));
+
+ if ((rc == LDAP_NAMING_VIOLATION) ||
+ (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
+ const char *attrs[] = { "sambaGroupType", "description",
+ "displayName", "sambaSIDList",
+ NULL };
+
+ /* Second try. Don't delete the sambaSID attribute, this is
+ for "old" entries that are tacked on a winbind
+ sambaIdmapEntry. */
+
+ rc = ldapsam_delete_entry(priv, mem_ctx, entry,
+ LDAP_OBJ_GROUPMAP, attrs);
}
- attr_list = get_attr_list( groupmap_attr_list_to_delete );
- ret = ldapsam_delete_entry(ldap_state, result, LDAP_OBJ_GROUPMAP, attr_list);
- free_attr_list ( attr_list );
+ if ((rc == LDAP_NAMING_VIOLATION) ||
+ (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
+ const char *attrs[] = { "sambaGroupType", "description",
+ "displayName", "sambaSIDList",
+ "gidNumber", NULL };
- ldap_msgfree(result);
+ /* Third try. This is a post-3.0.21 alias (containing only
+ * sambaSidEntry and sambaGroupMapping classes), we also have
+ * to delete the gidNumber attribute, only the sambaSidEntry
+ * remains */
- return ret;
-}
+ rc = ldapsam_delete_entry(priv, mem_ctx, entry,
+ LDAP_OBJ_GROUPMAP, attrs);
+ }
+
+ result = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+
+ done:
+ talloc_free(mem_ctx);
+ return result;
+ }
/**********************************************************************
*********************************************************************/
-static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
+static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
+ BOOL update)
{
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)my_methods->private_data;
fstring filter;
int rc;
const char **attr_list;
pstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
- attr_list = get_attr_list( groupmap_attr_list );
+ attr_list = get_attr_list( NULL, groupmap_attr_list );
rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
LDAP_SCOPE_SUBTREE, filter,
attr_list, 0, &ldap_state->result);
- free_attr_list( attr_list );
+ talloc_free(attr_list);
if (rc != LDAP_SUCCESS) {
- DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n", ldap_err2string(rc)));
- DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n", lp_ldap_group_suffix(), filter));
+ DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n",
+ ldap_err2string(rc)));
+ DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n",
+ lp_ldap_group_suffix(), filter));
ldap_msgfree(ldap_state->result);
ldap_state->result = NULL;
return NT_STATUS_UNSUCCESSFUL;
@@ -2992,7 +3066,9 @@ static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
ldap_state->result)));
- ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result);
+ ldap_state->entry =
+ ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
+ ldap_state->result);
ldap_state->index = 0;
return NT_STATUS_OK;
@@ -3013,7 +3089,8 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
GROUP_MAP *map)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)my_methods->private_data;
BOOL bret = False;
while (!bret) {
@@ -3021,10 +3098,12 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
return ret;
ldap_state->index++;
- bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
+ bret = init_group_from_ldap(ldap_state, map,
+ ldap_state->entry);
- ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
- ldap_state->entry);
+ ldap_state->entry =
+ ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
+ ldap_state->entry);
}
return NT_STATUS_OK;
@@ -3035,7 +3114,8 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
enum SID_NAME_USE sid_name_use,
- GROUP_MAP **pp_rmap, size_t *p_num_entries,
+ GROUP_MAP **pp_rmap,
+ size_t *p_num_entries,
BOOL unix_only)
{
GROUP_MAP map;
@@ -3046,24 +3126,28 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
*pp_rmap = NULL;
if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
- DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open passdb\n"));
+ DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open "
+ "passdb\n"));
return NT_STATUS_ACCESS_DENIED;
}
while (NT_STATUS_IS_OK(ldapsam_getsamgrent(methods, &map))) {
if (sid_name_use != SID_NAME_UNKNOWN &&
sid_name_use != map.sid_name_use) {
- DEBUG(11,("ldapsam_enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
+ DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
+ "not of the requested type\n", map.nt_name));
continue;
}
if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
- DEBUG(11,("ldapsam_enum_group_mapping: group %s is non mapped\n", map.nt_name));
+ DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
+ "non mapped\n", map.nt_name));
continue;
}
mapt=SMB_REALLOC_ARRAY((*pp_rmap), GROUP_MAP, entries+1);
if (!mapt) {
- DEBUG(0,("ldapsam_enum_group_mapping: Unable to enlarge group map!\n"));
+ DEBUG(0,("ldapsam_enum_group_mapping: Unable to "
+ "enlarge group map!\n"));
SAFE_FREE(*pp_rmap);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -3095,14 +3179,28 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
int count;
LDAPMod **mods = NULL;
int rc;
+ enum SID_NAME_USE type = SID_NAME_USE_NONE;
pstring filter;
- pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
- LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
- get_attr_key2string(groupmap_attr_list,
- LDAP_ATTR_GROUP_SID),
- sid_string_static(alias));
+ if (sid_check_is_in_builtin(alias)) {
+ type = SID_NAME_WKN_GRP;
+ }
+
+ if (sid_check_is_in_our_domain(alias)) {
+ type = SID_NAME_ALIAS;
+ }
+
+ if (type == SID_NAME_USE_NONE) {
+ DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
+ sid_string_static(alias)));
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
+ pstr_sprintf(filter,
+ "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
+ LDAP_OBJ_GROUPMAP, sid_string_static(alias),
+ type);
if (ldapsam_search_one_group(ldap_state, filter,
&result) != LDAP_SUCCESS)
@@ -3118,8 +3216,8 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
}
if (count > 1) {
- DEBUG(1, ("ldapsam_modify_aliasmem: Duplicate entries for filter %s: "
- "count=%d\n", filter, count));
+ DEBUG(1, ("ldapsam_modify_aliasmem: Duplicate entries for "
+ "filter %s: count=%d\n", filter, count));
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_ALIAS;
}
@@ -3147,22 +3245,20 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
ldap_mods_free(mods, True);
ldap_msgfree(result);
+ SAFE_FREE(dn);
+
+ if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
+ return NT_STATUS_MEMBER_IN_ALIAS;
+ }
+
+ if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
+ return NT_STATUS_MEMBER_NOT_IN_ALIAS;
+ }
if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct,
- LDAP_OPT_ERROR_STRING,&ld_error);
-
- DEBUG(0, ("ldapsam_modify_aliasmem: Could not modify alias "
- "for %s, error: %s (%s)\n", dn, ldap_err2string(rc),
- ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
- SAFE_FREE(dn);
return NT_STATUS_UNSUCCESSFUL;
}
- SAFE_FREE(dn);
-
return NT_STATUS_OK;
}
@@ -3182,7 +3278,8 @@ static NTSTATUS ldapsam_del_aliasmem(struct pdb_methods *methods,
}
static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
- const DOM_SID *alias, DOM_SID **pp_members,
+ const DOM_SID *alias,
+ DOM_SID **pp_members,
size_t *p_num_members)
{
struct ldapsam_privates *ldap_state =
@@ -3194,15 +3291,29 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
int i;
pstring filter;
size_t num_members = 0;
+ enum SID_NAME_USE type = SID_NAME_USE_NONE;
*pp_members = NULL;
*p_num_members = 0;
- pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
- LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
- get_attr_key2string(groupmap_attr_list,
- LDAP_ATTR_GROUP_SID),
- sid_string_static(alias));
+ if (sid_check_is_in_builtin(alias)) {
+ type = SID_NAME_WKN_GRP;
+ }
+
+ if (sid_check_is_in_our_domain(alias)) {
+ type = SID_NAME_ALIAS;
+ }
+
+ if (type == SID_NAME_USE_NONE) {
+ DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
+ sid_string_static(alias)));
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
+ pstr_sprintf(filter,
+ "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
+ LDAP_OBJ_GROUPMAP, sid_string_static(alias),
+ type);
if (ldapsam_search_one_group(ldap_state, filter,
&result) != LDAP_SUCCESS)
@@ -3218,8 +3329,8 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
}
if (count > 1) {
- DEBUG(1, ("ldapsam_enum_aliasmem: Duplicate entries for filter %s: "
- "count=%d\n", filter, count));
+ DEBUG(1, ("ldapsam_enum_aliasmem: Duplicate entries for "
+ "filter %s: count=%d\n", filter, count));
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_ALIAS;
}
@@ -3279,14 +3390,25 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
int i;
int rc;
char *filter;
+ enum SID_NAME_USE type = SID_NAME_USE_NONE;
+
+ if (sid_check_is_builtin(domain_sid)) {
+ type = SID_NAME_WKN_GRP;
+ }
- /* This query could be further optimized by adding a
- (&(sambaSID=<domain-sid>*)) so that only those aliases that are
- asked for in the getuseraliases are returned. */
+ if (sid_check_is_domain(domain_sid)) {
+ type = SID_NAME_ALIAS;
+ }
+
+ if (type == SID_NAME_USE_NONE) {
+ DEBUG(5, ("SID %s is neither builtin nor domain!\n",
+ sid_string_static(domain_sid)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
filter = talloc_asprintf(mem_ctx,
- "(&(|(objectclass=%s)(objectclass=%s))(|",
- LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY);
+ "(&(|(objectclass=%s)(sambaGroupType=%d))(|",
+ LDAP_OBJ_GROUPMAP, type);
for (i=0; i<num_members; i++)
filter = talloc_asprintf(mem_ctx, "%s(sambaSIDList=%s)",
@@ -3331,7 +3453,9 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
return NT_STATUS_OK;
}
-static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods, int policy_index, uint32 value)
+static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
+ int policy_index,
+ uint32 value)
{
NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
int rc;
@@ -3352,7 +3476,8 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
policy_attr = get_account_policy_attr(policy_index);
if (policy_attr == NULL) {
- DEBUG(0,("ldapsam_set_account_policy_in_ldap: invalid policy\n"));
+ DEBUG(0,("ldapsam_set_account_policy_in_ldap: invalid "
+ "policy\n"));
return ntstatus;
}
@@ -3363,40 +3488,39 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string);
- rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn, mods);
+ rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn,
+ mods);
ldap_mods_free(mods, True);
if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct,
- LDAP_OPT_ERROR_STRING,&ld_error);
-
- DEBUG(0, ("ldapsam_set_account_policy_in_ldap: Could not set account policy "
- "for %s, error: %s (%s)\n", ldap_state->domain_dn, ldap_err2string(rc),
- ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
return ntstatus;
}
if (!cache_account_policy_set(policy_index, value)) {
- DEBUG(0,("ldapsam_set_account_policy_in_ldap: failed to update local tdb cache\n"));
+ DEBUG(0,("ldapsam_set_account_policy_in_ldap: failed to "
+ "update local tdb cache\n"));
return ntstatus;
}
return NT_STATUS_OK;
}
-static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods, int policy_index, uint32 value)
+static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods,
+ int policy_index, uint32 value)
{
if (!account_policy_migrated(False)) {
- return (account_policy_set(policy_index, value)) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+ return (account_policy_set(policy_index, value)) ?
+ NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
}
- return ldapsam_set_account_policy_in_ldap(methods, policy_index, value);
+ return ldapsam_set_account_policy_in_ldap(methods, policy_index,
+ value);
}
-static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods, int policy_index, uint32 *value)
+static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods,
+ int policy_index,
+ uint32 *value)
{
NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
LDAPMessage *result = NULL;
@@ -3419,7 +3543,8 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods
policy_attr = get_account_policy_attr(policy_index);
if (!policy_attr) {
- DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid policy index: %d\n", policy_index));
+ DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid "
+ "policy index: %d\n", policy_index));
return ntstatus;
}
@@ -3427,31 +3552,24 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods
attrs[1] = NULL;
rc = smbldap_search(ldap_state->smbldap_state, ldap_state->domain_dn,
- LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &result);
+ LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0,
+ &result);
if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct,
- LDAP_OPT_ERROR_STRING,&ld_error);
-
- DEBUG(3, ("ldapsam_get_account_policy_from_ldap: Could not get account policy "
- "for %s, error: %s (%s)\n", ldap_state->domain_dn, ldap_err2string(rc),
- ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
return ntstatus;
}
- count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+ count = ldap_count_entries(priv2ld(ldap_state), result);
if (count < 1) {
goto out;
}
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
if (entry == NULL) {
goto out;
}
- vals = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, policy_attr);
+ vals = ldap_get_values(priv2ld(ldap_state), entry, policy_attr);
if (vals == NULL) {
goto out;
}
@@ -3470,7 +3588,8 @@ out:
/* wrapper around ldapsam_get_account_policy_from_ldap(), handles tdb as cache
- - if user hasn't decided to use account policies inside LDAP just reuse the old tdb values
+ - if user hasn't decided to use account policies inside LDAP just reuse the
+ old tdb values
- if there is a valid cache entry, return that
- if there is an LDAP entry, update cache and return
@@ -3478,32 +3597,38 @@ out:
Guenther
*/
-static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods, int policy_index, uint32 *value)
+static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods,
+ int policy_index, uint32 *value)
{
NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
if (!account_policy_migrated(False)) {
- return (account_policy_get(policy_index, value)) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+ return (account_policy_get(policy_index, value))
+ ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
}
if (cache_account_policy_get(policy_index, value)) {
- DEBUG(11,("ldapsam_get_account_policy: got valid value from cache\n"));
+ DEBUG(11,("ldapsam_get_account_policy: got valid value from "
+ "cache\n"));
return NT_STATUS_OK;
}
- ntstatus = ldapsam_get_account_policy_from_ldap(methods, policy_index, value);
+ ntstatus = ldapsam_get_account_policy_from_ldap(methods, policy_index,
+ value);
if (NT_STATUS_IS_OK(ntstatus)) {
goto update_cache;
}
- DEBUG(10,("ldapsam_get_account_policy: failed to retrieve from ldap\n"));
+ DEBUG(10,("ldapsam_get_account_policy: failed to retrieve from "
+ "ldap\n"));
#if 0
/* should we automagically migrate old tdb value here ? */
if (account_policy_get(policy_index, value))
goto update_ldap;
- DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying default\n", policy_index));
+ DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying "
+ "default\n", policy_index));
#endif
if (!account_policy_get_default(policy_index, value)) {
@@ -3520,7 +3645,8 @@ static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods, int poli
update_cache:
if (!cache_account_policy_set(policy_index, *value)) {
- DEBUG(0,("ldapsam_get_account_policy: failed to update local tdb as a cache\n"));
+ DEBUG(0,("ldapsam_get_account_policy: failed to update local "
+ "tdb as a cache\n"));
return NT_STATUS_UNSUCCESSFUL;
}
@@ -3536,39 +3662,44 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
- LDAP *ldap_struct = ldap_state->smbldap_state->ldap_struct;
LDAPMessage *msg = NULL;
LDAPMessage *entry;
char *allsids = NULL;
- char *tmp;
int i, rc, num_mapped;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ NTSTATUS result = NT_STATUS_NO_MEMORY;
+ TALLOC_CTX *mem_ctx;
+ LDAP *ld;
+ BOOL is_builtin;
- if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
- return pdb_default_lookup_rids(methods, domain_sid,
- num_rids, rids, names, attrs);
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ goto done;
+ }
- if (!sid_equal(domain_sid, get_global_sam_sid())) {
- /* TODO: Sooner or later we need to look up BUILTIN rids as
- * well. -- vl */
+ if (!sid_check_is_builtin(domain_sid) &&
+ !sid_check_is_domain(domain_sid)) {
+ result = NT_STATUS_INVALID_PARAMETER;
goto done;
}
for (i=0; i<num_rids; i++)
attrs[i] = SID_NAME_UNKNOWN;
- allsids = SMB_STRDUP("");
- if (allsids == NULL) return NT_STATUS_NO_MEMORY;
+ allsids = talloc_strdup(mem_ctx, "");
+ if (allsids == NULL) {
+ goto done;
+ }
for (i=0; i<num_rids; i++) {
DOM_SID sid;
sid_copy(&sid, domain_sid);
sid_append_rid(&sid, rids[i]);
- tmp = allsids;
- asprintf(&allsids, "%s(sambaSid=%s)", allsids,
- sid_string_static(&sid));
- if (allsids == NULL) return NT_STATUS_NO_MEMORY;
- free(tmp);
+ allsids = talloc_asprintf_append(allsids, "(sambaSid=%s)",
+ sid_string_static(&sid));
+ if (allsids == NULL) {
+ goto done;
+ }
}
/* First look for users */
@@ -3577,40 +3708,43 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
char *filter;
const char *ldap_attrs[] = { "uid", "sambaSid", NULL };
- asprintf(&filter, ("(&(objectClass=sambaSamAccount)(|%s))"),
- allsids);
- if (filter == NULL) return NT_STATUS_NO_MEMORY;
+ filter = talloc_asprintf(
+ mem_ctx, ("(&(objectClass=sambaSamAccount)(|%s))"),
+ allsids);
+
+ if (filter == NULL) {
+ goto done;
+ }
rc = smbldap_search(ldap_state->smbldap_state,
lp_ldap_user_suffix(),
LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
&msg);
-
- SAFE_FREE(filter);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
}
if (rc != LDAP_SUCCESS)
goto done;
+ ld = ldap_state->smbldap_state->ldap_struct;
num_mapped = 0;
- for (entry = ldap_first_entry(ldap_struct, msg);
+ for (entry = ldap_first_entry(ld, msg);
entry != NULL;
- entry = ldap_next_entry(ldap_struct, entry))
- {
+ entry = ldap_next_entry(ld, entry)) {
uint32 rid;
int rid_index;
- fstring str;
+ const char *name;
- if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
- get_global_sam_sid(),
+ if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
&rid)) {
DEBUG(2, ("Could not find sid from ldap entry\n"));
continue;
}
- if (!smbldap_get_single_attribute(ldap_struct, entry,
- "uid", str, sizeof(str)-1)) {
+ name = smbldap_talloc_single_attribute(ld, entry, "uid",
+ names);
+ if (name == NULL) {
DEBUG(2, ("Could not retrieve uid attribute\n"));
continue;
}
@@ -3626,9 +3760,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
}
attrs[rid_index] = SID_NAME_USER;
- names[rid_index] = talloc_strdup(names, str);
- if (names[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
-
+ names[rid_index] = name;
num_mapped += 1;
}
@@ -3638,49 +3770,83 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
goto done;
}
- if (msg != NULL) {
- ldap_msgfree(msg);
- }
-
/* Same game for groups */
{
char *filter;
- const char *ldap_attrs[] = { "cn", "sambaSid", NULL };
+ const char *ldap_attrs[] = { "cn", "displayName", "sambaSid",
+ "sambaGroupType", NULL };
- asprintf(&filter, ("(&(objectClass=sambaGroupMapping)(|%s))"),
- allsids);
- if (filter == NULL) return NT_STATUS_NO_MEMORY;
+ filter = talloc_asprintf(
+ mem_ctx, "(&(objectClass=sambaGroupMapping)(|%s))",
+ allsids);
+ if (filter == NULL) {
+ goto done;
+ }
rc = smbldap_search(ldap_state->smbldap_state,
lp_ldap_group_suffix(),
LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
&msg);
-
- SAFE_FREE(filter);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
}
if (rc != LDAP_SUCCESS)
goto done;
- for (entry = ldap_first_entry(ldap_struct, msg);
+ /* ldap_struct might have changed due to a reconnect */
+
+ ld = ldap_state->smbldap_state->ldap_struct;
+
+ /* For consistency checks, we already checked we're only domain or builtin */
+
+ is_builtin = sid_check_is_builtin(domain_sid);
+
+ for (entry = ldap_first_entry(ld, msg);
entry != NULL;
- entry = ldap_next_entry(ldap_struct, entry))
+ entry = ldap_next_entry(ld, entry))
{
uint32 rid;
int rid_index;
- fstring str;
+ const char *attr;
+ enum SID_NAME_USE type;
+ const char *dn = smbldap_talloc_dn(mem_ctx, ld, entry);
+
+ attr = smbldap_talloc_single_attribute(ld, entry, "sambaGroupType",
+ mem_ctx);
+ if (attr == NULL) {
+ DEBUG(2, ("Could not extract type from ldap entry %s\n",
+ dn));
+ continue;
+ }
- if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
- get_global_sam_sid(),
+ type = atol(attr);
+
+ /* Consistency checks */
+ if ((is_builtin && (type != SID_NAME_WKN_GRP)) ||
+ (!is_builtin && ((type != SID_NAME_ALIAS) &&
+ (type != SID_NAME_DOM_GRP)))) {
+ DEBUG(2, ("Rejecting invalid group mapping entry %s\n", dn));
+ }
+
+ if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
&rid)) {
- DEBUG(2, ("Could not find sid from ldap entry\n"));
+ DEBUG(2, ("Could not find sid from ldap entry %s\n", dn));
continue;
}
- if (!smbldap_get_single_attribute(ldap_struct, entry,
- "cn", str, sizeof(str)-1)) {
- DEBUG(2, ("Could not retrieve cn attribute\n"));
+ attr = smbldap_talloc_single_attribute(ld, entry, "cn", names);
+
+ if (attr == NULL) {
+ DEBUG(10, ("Could not retrieve 'cn' attribute from %s\n",
+ dn));
+ attr = smbldap_talloc_single_attribute(
+ ld, entry, "displayName", names);
+ }
+
+ if (attr == NULL) {
+ DEBUG(2, ("Could not retrieve naming attribute from %s\n",
+ dn));
continue;
}
@@ -3694,9 +3860,8 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
continue;
}
- attrs[rid_index] = SID_NAME_DOM_GRP;
- names[rid_index] = talloc_strdup(names, str);
- if (names[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
+ attrs[rid_index] = type;
+ names[rid_index] = attr;
num_mapped += 1;
}
@@ -3706,11 +3871,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
result = (num_mapped == num_rids) ?
NT_STATUS_OK : STATUS_SOME_UNMAPPED;
done:
- SAFE_FREE(allsids);
-
- if (msg != NULL)
- ldap_msgfree(msg);
-
+ talloc_free(mem_ctx);
return result;
}
@@ -3833,7 +3994,6 @@ static BOOL ldapsam_search_firstpage(struct pdb_search *search)
static BOOL ldapsam_search_nextpage(struct pdb_search *search)
{
struct ldap_search_state *state = search->private_data;
- LDAP *ld = state->connection->ldap_struct;
int rc;
if (!state->connection->paged_results) {
@@ -3850,7 +4010,7 @@ static BOOL ldapsam_search_nextpage(struct pdb_search *search)
if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
return False;
- state->current_entry = ldap_first_entry(ld, state->entries);
+ state->current_entry = ldap_first_entry(state->connection->ldap_struct, state->entries);
if (state->current_entry == NULL) {
ldap_msgfree(state->entries);
@@ -3864,7 +4024,6 @@ static BOOL ldapsam_search_next_entry(struct pdb_search *search,
struct samr_displayentry *entry)
{
struct ldap_search_state *state = search->private_data;
- LDAP *ld = state->connection->ldap_struct;
BOOL result;
retry:
@@ -3875,17 +4034,17 @@ static BOOL ldapsam_search_next_entry(struct pdb_search *search,
!ldapsam_search_nextpage(search))
return False;
- result = state->ldap2displayentry(state, search->mem_ctx, ld,
+ result = state->ldap2displayentry(state, search->mem_ctx, state->connection->ldap_struct,
state->current_entry, entry);
if (!result) {
char *dn;
- dn = ldap_get_dn(ld, state->current_entry);
+ dn = ldap_get_dn(state->connection->ldap_struct, state->current_entry);
DEBUG(5, ("Skipping entry %s\n", dn != NULL ? dn : "<NULL>"));
if (dn != NULL) ldap_memfree(dn);
}
- state->current_entry = ldap_next_entry(ld, state->current_entry);
+ state->current_entry = ldap_next_entry(state->connection->ldap_struct, state->current_entry);
if (state->current_entry == NULL) {
ldap_msgfree(state->entries);
@@ -4002,7 +4161,8 @@ static BOOL ldapuser2displayentry(struct ldap_search_state *state,
ldap_value_free(vals);
if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
- DEBUG(0, ("sid %s does not belong to our domain\n", sid_string_static(&sid)));
+ DEBUG(0, ("sid %s does not belong to our domain\n",
+ sid_string_static(&sid)));
return False;
}
@@ -4102,10 +4262,14 @@ static BOOL ldapgroup2displayentry(struct ldap_search_state *state,
DEBUG(5, ("\"cn\" not found\n"));
return False;
}
- pull_utf8_talloc(mem_ctx, CONST_DISCARD(char **, &result->account_name), vals[0]);
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->account_name),
+ vals[0]);
}
else {
- pull_utf8_talloc(mem_ctx, CONST_DISCARD(char **, &result->account_name), vals[0]);
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->account_name),
+ vals[0]);
}
ldap_value_free(vals);
@@ -4146,17 +4310,21 @@ static BOOL ldapgroup2displayentry(struct ldap_search_state *state,
case SID_NAME_DOM_GRP:
case SID_NAME_ALIAS:
- if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
- DEBUG(0, ("%s is not in our domain\n", sid_string_static(&sid)));
+ if (!sid_peek_check_rid(get_global_sam_sid(), &sid,
+ &result->rid)) {
+ DEBUG(0, ("%s is not in our domain\n",
+ sid_string_static(&sid)));
return False;
}
break;
case SID_NAME_WKN_GRP:
- if (!sid_peek_check_rid(&global_sid_Builtin, &sid, &result->rid)) {
+ if (!sid_peek_check_rid(&global_sid_Builtin, &sid,
+ &result->rid)) {
- DEBUG(0, ("%s is not in builtin sid\n", sid_string_static(&sid)));
+ DEBUG(0, ("%s is not in builtin sid\n",
+ sid_string_static(&sid)));
return False;
}
break;
@@ -4191,7 +4359,8 @@ static BOOL ldapsam_search_grouptype(struct pdb_methods *methods,
"(&(objectclass=sambaGroupMapping)"
"(sambaGroupType=%d))", type);
state->attrs = talloc_attrs(search->mem_ctx, "cn", "sambaSid",
- "displayName", "description", "sambaGroupType", NULL);
+ "displayName", "description",
+ "sambaGroupType", NULL);
state->attrsonly = 0;
state->pagedresults_cookie = NULL;
state->entries = NULL;
@@ -4232,6 +4401,214 @@ static BOOL ldapsam_search_aliases(struct pdb_methods *methods,
return False;
}
+static BOOL ldapsam_rid_algorithm(struct pdb_methods *methods)
+{
+ return False;
+}
+
+static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
+ uint32 *rid)
+{
+ struct smbldap_state *smbldap_state = priv->smbldap_state;
+
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ LDAPMod **mods = NULL;
+ NTSTATUS status;
+ char *value;
+ int rc;
+ uint32 nextRid = 0;
+
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = smbldap_search_domain_info(smbldap_state, &result,
+ get_global_sam_name(), False);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("Could not get domain info: %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
+ entry = ldap_first_entry(priv2ld(priv), result);
+ if (entry == NULL) {
+ DEBUG(0, ("Could not get domain info entry\n"));
+ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
+
+ /* Find the largest of the three attributes "sambaNextRid",
+ "sambaNextGroupRid" and "sambaNextUserRid". I gave up on the
+ concept of differentiating between user and group rids, and will
+ use only "sambaNextRid" in the future. But for compatibility
+ reasons I look if others have chosen different strategies -- VL */
+
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "sambaNextRid", mem_ctx);
+ if (value != NULL) {
+ uint32 tmp = (uint32)strtoul(value, NULL, 10);
+ nextRid = MAX(nextRid, tmp);
+ }
+
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "sambaNextUserRid", mem_ctx);
+ if (value != NULL) {
+ uint32 tmp = (uint32)strtoul(value, NULL, 10);
+ nextRid = MAX(nextRid, tmp);
+ }
+
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "sambaNextGroupRid", mem_ctx);
+ if (value != NULL) {
+ uint32 tmp = (uint32)strtoul(value, NULL, 10);
+ nextRid = MAX(nextRid, tmp);
+ }
+
+ if (nextRid == 0) {
+ nextRid = BASE_RID-1;
+ }
+
+ nextRid += 1;
+
+ smbldap_make_mod(priv2ld(priv), entry, &mods, "sambaNextRid",
+ talloc_asprintf(mem_ctx, "%d", nextRid));
+ talloc_autofree_ldapmod(mem_ctx, mods);
+
+ rc = smbldap_modify(smbldap_state,
+ smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry),
+ mods);
+
+ /* ACCESS_DENIED is used as a placeholder for "the modify failed,
+ * please retry" */
+
+ status = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+
+ done:
+ if (NT_STATUS_IS_OK(status)) {
+ *rid = nextRid;
+ }
+
+ talloc_free(mem_ctx);
+ return status;
+}
+
+static BOOL ldapsam_new_rid(struct pdb_methods *methods, uint32 *rid)
+{
+ int i;
+
+ for (i=0; i<10; i++) {
+ NTSTATUS result = ldapsam_get_new_rid(methods->private_data,
+ rid);
+ if (NT_STATUS_IS_OK(result)) {
+ return True;
+ }
+
+ if (!NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
+ return False;
+ }
+
+ /* The ldap update failed (maybe a race condition), retry */
+ }
+
+ /* Tried 10 times, fail. */
+ return False;
+}
+
+static BOOL ldapsam_sid_to_id(struct pdb_methods *methods,
+ const DOM_SID *sid,
+ union unid_t *id, enum SID_NAME_USE *type)
+{
+ struct ldapsam_privates *priv = methods->private_data;
+ char *filter;
+ const char *attrs[] = { "sambaGroupType", "gidNumber", "uidNumber",
+ NULL };
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ BOOL ret = False;
+ char *value;
+ int rc;
+
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return False;
+ }
+
+ filter = talloc_asprintf(mem_ctx,
+ "(&(sambaSid=%s)"
+ "(|(objectClass=sambaGroupMapping)"
+ "(objectClass=sambaSamAccount)))",
+ sid_string_static(sid));
+ if (filter == NULL) {
+ DEBUG(5, ("talloc_asprintf failed\n"));
+ goto done;
+ }
+
+ rc = smbldap_search_suffix(priv->smbldap_state, filter,
+ attrs, &result);
+ if (rc != LDAP_SUCCESS) {
+ goto done;
+ }
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
+ if (ldap_count_entries(priv2ld(priv), result) != 1) {
+ DEBUG(10, ("Got %d entries, expected one\n",
+ ldap_count_entries(priv2ld(priv), result)));
+ goto done;
+ }
+
+ entry = ldap_first_entry(priv2ld(priv), result);
+
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "sambaGroupType", mem_ctx);
+
+ if (value != NULL) {
+ const char *gid_str;
+ /* It's a group */
+
+ gid_str = smbldap_talloc_single_attribute(
+ priv2ld(priv), entry, "gidNumber", mem_ctx);
+ if (gid_str == NULL) {
+ DEBUG(1, ("%s has sambaGroupType but no gidNumber\n",
+ smbldap_talloc_dn(mem_ctx, priv2ld(priv),
+ entry)));
+ goto done;
+ }
+
+ id->gid = strtoul(gid_str, NULL, 10);
+ *type = strtoul(value, NULL, 10);
+ ret = True;
+ goto done;
+ }
+
+ /* It must be a user */
+
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "uidNumber", mem_ctx);
+ if (value == NULL) {
+ DEBUG(1, ("Could not find uidNumber in %s\n",
+ smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry)));
+ goto done;
+ }
+
+ id->uid = strtoul(value, NULL, 10);
+ *type = SID_NAME_USER;
+
+ ret = True;
+ done:
+ talloc_free(mem_ctx);
+ return ret;
+}
+
/**********************************************************************
Housekeeping
*********************************************************************/
@@ -4288,15 +4665,15 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **
(*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
(*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
(*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
- (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
- (*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships;
- (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
(*pdb_method)->get_account_policy = ldapsam_get_account_policy;
(*pdb_method)->set_account_policy = ldapsam_set_account_policy;
(*pdb_method)->get_seq_num = ldapsam_get_seq_num;
+ (*pdb_method)->rid_algorithm = ldapsam_rid_algorithm;
+ (*pdb_method)->new_rid = ldapsam_new_rid;
+
/* TODO: Setup private data and free */
ldap_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct ldapsam_privates);
@@ -4377,7 +4754,8 @@ NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, co
pstring domain_sid_string;
char *dn;
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
+ nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location);
+ if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
@@ -4391,27 +4769,41 @@ NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, co
(*pdb_method)->search_groups = ldapsam_search_groups;
(*pdb_method)->search_aliases = ldapsam_search_aliases;
+ if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+ (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
+ (*pdb_method)->enum_group_memberships =
+ ldapsam_enum_group_memberships;
+ (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
+ (*pdb_method)->sid_to_id = ldapsam_sid_to_id;
+ }
+
ldap_state = (*pdb_method)->private_data;
ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
/* Try to setup the Domain Name, Domain SID, algorithmic rid base */
- nt_status = smbldap_search_domain_info(ldap_state->smbldap_state, &result,
+ nt_status = smbldap_search_domain_info(ldap_state->smbldap_state,
+ &result,
ldap_state->domain_name, True);
if ( !NT_STATUS_IS_OK(nt_status) ) {
- DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain info, nor add one to the domain\n"));
- DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, will be unable to allocate new users/groups, \
-and will risk BDCs having inconsistant SIDs\n"));
+ DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain "
+ "info, nor add one to the domain\n"));
+ DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, "
+ "will be unable to allocate new users/groups, "
+ "and will risk BDCs having inconsistant SIDs\n"));
sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
return NT_STATUS_OK;
}
- /* Given that the above might fail, everything below this must be optional */
+ /* Given that the above might fail, everything below this must be
+ * optional */
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+ entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
+ result);
if (!entry) {
- DEBUG(0, ("pdb_init_ldapsam: Could not get domain info entry\n"));
+ DEBUG(0, ("pdb_init_ldapsam: Could not get domain info "
+ "entry\n"));
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -4424,35 +4816,51 @@ and will risk BDCs having inconsistant SIDs\n"));
ldap_state->domain_dn = smb_xstrdup(dn);
ldap_memfree(dn);
- if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
- domain_sid_string)) {
+ if (smbldap_get_single_pstring(
+ ldap_state->smbldap_state->ldap_struct,
+ entry,
+ get_userattr_key2string(ldap_state->schema_ver,
+ LDAP_ATTR_USER_SID),
+ domain_sid_string)) {
BOOL found_sid;
if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
- DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be read as a valid SID\n", domain_sid_string));
+ DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be "
+ "read as a valid SID\n", domain_sid_string));
return NT_STATUS_INVALID_PARAMETER;
}
- found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid);
- if (!found_sid || !sid_equal(&secrets_domain_sid, &ldap_domain_sid)) {
+ found_sid = secrets_fetch_domain_sid(ldap_state->domain_name,
+ &secrets_domain_sid);
+ if (!found_sid || !sid_equal(&secrets_domain_sid,
+ &ldap_domain_sid)) {
fstring new_sid_str, old_sid_str;
- DEBUG(1, ("pdb_init_ldapsam: Resetting SID for domain %s based on pdb_ldap results %s -> %s\n",
- ldap_state->domain_name,
- sid_to_string(old_sid_str, &secrets_domain_sid),
- sid_to_string(new_sid_str, &ldap_domain_sid)));
+ DEBUG(1, ("pdb_init_ldapsam: Resetting SID for domain "
+ "%s based on pdb_ldap results %s -> %s\n",
+ ldap_state->domain_name,
+ sid_to_string(old_sid_str,
+ &secrets_domain_sid),
+ sid_to_string(new_sid_str,
+ &ldap_domain_sid)));
/* reset secrets.tdb sid */
- secrets_store_domain_sid(ldap_state->domain_name, &ldap_domain_sid);
- DEBUG(1, ("New global sam SID: %s\n", sid_to_string(new_sid_str, get_global_sam_sid())));
+ secrets_store_domain_sid(ldap_state->domain_name,
+ &ldap_domain_sid);
+ DEBUG(1, ("New global sam SID: %s\n",
+ sid_to_string(new_sid_str,
+ get_global_sam_sid())));
}
sid_copy(&ldap_state->domain_sid, &ldap_domain_sid);
}
- if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_attr_key2string( dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE ),
- alg_rid_base_string)) {
+ if (smbldap_get_single_pstring(
+ ldap_state->smbldap_state->ldap_struct,
+ entry,
+ get_attr_key2string( dominfo_attr_list,
+ LDAP_ATTR_ALGORITHMIC_RID_BASE ),
+ alg_rid_base_string)) {
alg_rid_base = (uint32)atol(alg_rid_base_string);
if (alg_rid_base != algorithmic_rid_base()) {
- DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n"
+ DEBUG(0, ("The value of 'algorithmic RID base' has "
+ "changed since the LDAP\n"
"database was initialised. Aborting. \n"));
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
diff --git a/source3/passdb/pdb_nds.c b/source3/passdb/pdb_nds.c
index cf2d1d7c8a..49c3c9db06 100644
--- a/source3/passdb/pdb_nds.c
+++ b/source3/passdb/pdb_nds.c
@@ -771,13 +771,16 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
result = pdb_get_backend_private_data(sam_acct, methods);
if (!result) {
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL,
+ ldap_state->schema_ver);
rc = ldapsam_search_suffix_by_name(ldap_state, username, &result, attr_list );
- free_attr_list( attr_list );
+ talloc_free( attr_list );
if (rc != LDAP_SUCCESS) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- pdb_set_backend_private_data(sam_acct, result, private_data_free_fn, methods, PDB_CHANGED);
+ pdb_set_backend_private_data(sam_acct, result, NULL,
+ methods, PDB_CHANGED);
+ talloc_autofree_ldapmsg(sam_acct->mem_ctx, result);
}
if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c
index 487df96e95..06a3f4f4a1 100644
--- a/source3/passdb/pdb_smbpasswd.c
+++ b/source3/passdb/pdb_smbpasswd.c
@@ -594,7 +594,6 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str
size_t new_entry_length;
char *new_entry;
SMB_OFF_T offpos;
- uint32 max_found_uid = 0;
/* Open the smbpassword file - for update. */
fp = startsmbfilepwent(pfile, PWF_UPDATE, &smbpasswd_state->pw_file_lock_depth);
@@ -619,11 +618,6 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str
endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
return False;
}
-
- /* Look for a free uid for use in non-unix accounts */
- if (pwd->smb_userid > max_found_uid) {
- max_found_uid = pwd->smb_userid;
- }
}
/* Ok - entry doesn't exist. We can add it */
@@ -1161,14 +1155,13 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas
/* If the user specified a RID, make sure its able to be both stored and retreived */
if (rid == DOMAIN_USER_RID_GUEST) {
- struct passwd *passwd = getpwnam_alloc(lp_guestaccount());
+ struct passwd *passwd = getpwnam_alloc(NULL, lp_guestaccount());
if (!passwd) {
DEBUG(0, ("Could not find gest account via getpwnam()! (%s)\n", lp_guestaccount()));
return False;
}
smb_pw->smb_userid=passwd->pw_uid;
- passwd_free(&passwd);
-
+ talloc_free(passwd);
} else if (algorithmic_pdb_rid_is_user(rid)) {
smb_pw->smb_userid=algorithmic_pdb_user_rid_to_uid(rid);
} else {
@@ -1204,7 +1197,7 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state,
/* verify the user account exists */
- if ( !(pwfile = getpwnam_alloc(pw_buf->smb_name)) ) {
+ if ( !(pwfile = getpwnam_alloc(NULL, pw_buf->smb_name)) ) {
DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s with uid "
"%u is not in unix passwd database!\n", pw_buf->smb_name, pw_buf->smb_userid));
return False;
@@ -1213,7 +1206,7 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state,
if (!NT_STATUS_IS_OK(pdb_fill_sam_pw(sam_pass, pwfile)))
return False;
- passwd_free(&pwfile);
+ talloc_free(pwfile);
/* set remaining fields */
@@ -1532,6 +1525,11 @@ done:
return (ret);
}
+static BOOL smbpasswd_rid_algorithm(struct pdb_methods *methods)
+{
+ return True;
+}
+
static void free_private_data(void **vp)
{
struct smbpasswd_privates **privates = (struct smbpasswd_privates**)vp;
@@ -1563,6 +1561,8 @@ static NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_m
(*pdb_method)->delete_sam_account = smbpasswd_delete_sam_account;
(*pdb_method)->rename_sam_account = smbpasswd_rename_sam_account;
+ (*pdb_method)->rid_algorithm = smbpasswd_rid_algorithm;
+
/* Setup private data and free function */
privates = TALLOC_ZERO_P(pdb_context->mem_ctx, struct smbpasswd_privates);
diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c
index 370c8adc7d..74f47e70dc 100644
--- a/source3/passdb/pdb_tdb.c
+++ b/source3/passdb/pdb_tdb.c
@@ -864,7 +864,98 @@ done:
return (ret);
}
-
+
+static BOOL tdbsam_rid_algorithm(struct pdb_methods *methods)
+{
+ return False;
+}
+
+/*
+ * Historically, winbind was responsible for allocating RIDs, so the next RID
+ * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
+ * but for compatibility reasons we still keep the the next RID counter in
+ * winbindd_idmap.tdb.
+ */
+
+/*****************************************************************************
+ Initialise idmap database. For now (Dec 2005) this is a copy of the code in
+ sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
+ winbind completely and store the RID counter in passdb.tdb.
+
+ Dont' fully initialize with the HWM values, if it's new, we're only
+ interested in the RID counter.
+*****************************************************************************/
+
+static BOOL init_idmap_tdb(TDB_CONTEXT *tdb)
+{
+ int32 version;
+
+ if (tdb_lock_bystring(tdb, "IDMAP_VERSION", 0) != 0) {
+ DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
+ return False;
+ }
+
+ version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
+
+ if (version == -1) {
+ /* No key found, must be a new db */
+ if (tdb_store_int32(tdb, "IDMAP_VERSION",
+ IDMAP_VERSION) != 0) {
+ DEBUG(0, ("Could not store IDMAP_VERSION\n"));
+ tdb_unlock_bystring(tdb, "IDMAP_VERSION");
+ return False;
+ }
+ version = IDMAP_VERSION;
+ }
+
+ if (version != IDMAP_VERSION) {
+ DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
+ "start winbind once\n", IDMAP_VERSION, version));
+ tdb_unlock_bystring(tdb, "IDMAP_VERSION");
+ return False;
+ }
+
+ tdb_unlock_bystring(tdb, "IDMAP_VERSION");
+ return True;
+}
+
+static BOOL tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
+{
+ TDB_CONTEXT *tdb;
+ uint32 rid;
+ BOOL ret = False;
+
+ tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
+ TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
+
+ if (tdb == NULL) {
+ DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
+ goto done;
+ }
+
+ if (!init_idmap_tdb(tdb)) {
+ DEBUG(1, ("Could not init idmap\n"));
+ goto done;
+ }
+
+ rid = BASE_RID; /* Default if not set */
+
+ if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
+ DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
+ goto done;
+ }
+
+ *prid = rid;
+ ret = True;
+
+ done:
+ if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
+ smb_panic("tdb_close(idmap_tdb) failed\n");
+ }
+
+ return ret;
+}
+
static void free_private_data(void **vp)
{
struct tdbsam_privates **tdb_state = (struct tdbsam_privates **)vp;
@@ -908,6 +999,9 @@ static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_meth
(*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
(*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
+ (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
+ (*pdb_method)->new_rid = tdbsam_new_rid;
+
tdb_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct tdbsam_privates);
if (!tdb_state) {
diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c
index 88dabbd644..69bafc7ce5 100644
--- a/source3/passdb/secrets.c
+++ b/source3/passdb/secrets.c
@@ -388,10 +388,11 @@ BOOL secrets_store_trust_account_password(const char *domain, uint8 new_pwd[16])
* @return true if succeeded
**/
-BOOL secrets_store_trusted_domain_password(const char* domain, smb_ucs2_t *uni_dom_name,
- size_t uni_name_len, const char* pwd,
- DOM_SID sid)
-{
+BOOL secrets_store_trusted_domain_password(const char* domain, const char* pwd,
+ const DOM_SID *sid)
+{
+ smb_ucs2_t *uni_dom_name;
+
/* packing structures */
pstring pass_buf;
int pass_len = 0;
@@ -399,13 +400,15 @@ BOOL secrets_store_trusted_domain_password(const char* domain, smb_ucs2_t *uni_d
struct trusted_dom_pass pass;
ZERO_STRUCT(pass);
-
- /* unicode domain name and its length */
- if (!uni_dom_name)
+
+ if (push_ucs2_allocate(&uni_dom_name, domain) < 0) {
+ DEBUG(0, ("Could not convert domain name %s to unicode\n",
+ domain));
return False;
-
+ }
+
strncpy_w(pass.uni_name, uni_dom_name, sizeof(pass.uni_name) - 1);
- pass.uni_name_len = uni_name_len;
+ pass.uni_name_len = strlen_w(uni_dom_name)+1;
/* last change time */
pass.mod_time = time(NULL);
@@ -415,7 +418,7 @@ BOOL secrets_store_trusted_domain_password(const char* domain, smb_ucs2_t *uni_d
fstrcpy(pass.pass, pwd);
/* domain sid */
- sid_copy(&pass.domain_sid, &sid);
+ sid_copy(&pass.domain_sid, sid);
pass_len = tdb_trusted_dom_pass_pack(pass_buf, pass_buf_len, &pass);
@@ -658,138 +661,97 @@ BOOL fetch_ldap_pw(char **dn, char** pw)
/**
* Get trusted domains info from secrets.tdb.
- *
- * The linked list is allocated on the supplied talloc context, caller gets to destroy
- * when done.
- *
- * @param ctx Allocation context
- * @param enum_ctx Starting index, eg. we can start fetching at third
- * or sixth trusted domain entry. Zero is the first index.
- * Value it is set to is the enum context for the next enumeration.
- * @param num_domains Number of domain entries to fetch at one call
- * @param domains Pointer to array of trusted domain structs to be filled up
- *
- * @return nt status code of rpc response
**/
-NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, unsigned int max_num_domains,
- int *num_domains, TRUSTDOM ***domains)
+NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
+ struct trustdom_info ***domains)
{
TDB_LIST_NODE *keys, *k;
- TRUSTDOM *dom = NULL;
char *pattern;
- unsigned int start_idx;
- uint32 idx = 0;
- size_t size = 0, packed_size = 0;
- fstring dom_name;
- char *packed_pass;
- struct trusted_dom_pass *pass = TALLOC_ZERO_P(ctx, struct trusted_dom_pass);
- NTSTATUS status;
if (!secrets_init()) return NT_STATUS_ACCESS_DENIED;
- if (!pass) {
- DEBUG(0, ("talloc_zero failed!\n"));
- return NT_STATUS_NO_MEMORY;
- }
-
- *num_domains = 0;
- start_idx = *enum_ctx;
-
/* generate searching pattern */
- if (!(pattern = talloc_asprintf(ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS))) {
- DEBUG(0, ("secrets_get_trusted_domains: talloc_asprintf() failed!\n"));
+ pattern = talloc_asprintf(mem_ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS);
+ if (pattern == NULL) {
+ DEBUG(0, ("secrets_trusted_domains: talloc_asprintf() "
+ "failed!\n"));
return NT_STATUS_NO_MEMORY;
}
- DEBUG(5, ("secrets_get_trusted_domains: looking for %d domains, starting at index %d\n",
- max_num_domains, *enum_ctx));
-
- *domains = TALLOC_ZERO_ARRAY(ctx, TRUSTDOM *, max_num_domains);
+ *domains = NULL;
+ *num_domains = 0;
/* fetching trusted domains' data and collecting them in a list */
keys = tdb_search_keys(tdb, pattern);
- /*
- * if there's no keys returned ie. no trusted domain,
- * return "no more entries" code
- */
- status = NT_STATUS_NO_MORE_ENTRIES;
-
/* searching for keys in secrets db -- way to go ... */
for (k = keys; k; k = k->next) {
+ char *packed_pass;
+ size_t size = 0, packed_size = 0;
+ struct trusted_dom_pass pass;
char *secrets_key;
+ struct trustdom_info *dom_info;
/* important: ensure null-termination of the key string */
- secrets_key = SMB_STRNDUP(k->node_key.dptr, k->node_key.dsize);
+ secrets_key = talloc_strndup(mem_ctx,
+ k->node_key.dptr,
+ k->node_key.dsize);
if (!secrets_key) {
DEBUG(0, ("strndup failed!\n"));
return NT_STATUS_NO_MEMORY;
}
packed_pass = secrets_fetch(secrets_key, &size);
- packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size, pass);
+ packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size,
+ &pass);
/* packed representation isn't needed anymore */
SAFE_FREE(packed_pass);
if (size != packed_size) {
- DEBUG(2, ("Secrets record %s is invalid!\n", secrets_key));
+ DEBUG(2, ("Secrets record %s is invalid!\n",
+ secrets_key));
continue;
}
-
- pull_ucs2_fstring(dom_name, pass->uni_name);
- DEBUG(18, ("Fetched secret record num %d.\nDomain name: %s, SID: %s\n",
- idx, dom_name, sid_string_static(&pass->domain_sid)));
-
- SAFE_FREE(secrets_key);
-
- if (idx >= start_idx && idx < start_idx + max_num_domains) {
- dom = TALLOC_ZERO_P(ctx, TRUSTDOM);
- if (!dom) {
- /* free returned tdb record */
- return NT_STATUS_NO_MEMORY;
- }
-
- /* copy domain sid */
- SMB_ASSERT(sizeof(dom->sid) == sizeof(pass->domain_sid));
- memcpy(&(dom->sid), &(pass->domain_sid), sizeof(dom->sid));
-
- /* copy unicode domain name */
- dom->name = TALLOC_MEMDUP(ctx, pass->uni_name,
- (strlen_w(pass->uni_name) + 1) * sizeof(smb_ucs2_t));
-
- (*domains)[idx - start_idx] = dom;
-
- DEBUG(18, ("Secret record is in required range.\n \
- start_idx = %d, max_num_domains = %d. Added to returned array.\n",
- start_idx, max_num_domains));
- *enum_ctx = idx + 1;
- (*num_domains)++;
-
- /* set proper status code to return */
- if (k->next) {
- /* there are yet some entries to enumerate */
- status = STATUS_MORE_ENTRIES;
- } else {
- /* this is the last entry in the whole enumeration */
- status = NT_STATUS_OK;
- }
- } else {
- DEBUG(18, ("Secret is outside the required range.\n \
- start_idx = %d, max_num_domains = %d. Not added to returned array\n",
- start_idx, max_num_domains));
+ if (pass.domain_sid.num_auths != 4) {
+ DEBUG(0, ("SID %s is not a domain sid, has %d "
+ "auths instead of 4\n",
+ sid_string_static(&pass.domain_sid),
+ pass.domain_sid.num_auths));
+ continue;
}
-
- idx++;
+
+ dom_info = TALLOC_P(mem_ctx, struct trustdom_info);
+ if (dom_info == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (pull_ucs2_talloc(mem_ctx, &dom_info->name,
+ pass.uni_name) < 0) {
+ DEBUG(2, ("pull_ucs2_talloc failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ sid_copy(&dom_info->sid, &pass.domain_sid);
+
+ ADD_TO_ARRAY(mem_ctx, struct trustdom_info *, dom_info,
+ domains, num_domains);
+
+ if (*domains == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ talloc_steal(*domains, dom_info);
}
- DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n", *num_domains));
+ DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n",
+ *num_domains));
/* free the results of searching the keys */
tdb_search_list_free(keys);
- return status;
+ return NT_STATUS_OK;
}
/*******************************************************************************
diff --git a/source3/passdb/util_builtin.c b/source3/passdb/util_builtin.c
index 12a98d24dd..9c59df1f68 100644
--- a/source3/passdb/util_builtin.c
+++ b/source3/passdb/util_builtin.c
@@ -105,6 +105,6 @@ BOOL sid_check_is_in_builtin(const DOM_SID *sid)
sid_copy(&dom_sid, sid);
sid_split_rid(&dom_sid, &rid);
- return sid_equal(&dom_sid, &global_sid_Builtin);
+ return sid_check_is_builtin(&dom_sid);
}
diff --git a/source3/passdb/util_unixsids.c b/source3/passdb/util_unixsids.c
new file mode 100644
index 0000000000..ee8cf2d8f0
--- /dev/null
+++ b/source3/passdb/util_unixsids.c
@@ -0,0 +1,94 @@
+/*
+ Unix SMB/CIFS implementation.
+ Translate unix-defined names to SIDs and vice versa
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+BOOL sid_check_is_unix_users(const DOM_SID *sid)
+{
+ return sid_equal(sid, &global_sid_Unix_Users);
+}
+
+BOOL sid_check_is_in_unix_users(const DOM_SID *sid)
+{
+ DOM_SID dom_sid;
+ uint32 rid;
+
+ sid_copy(&dom_sid, sid);
+ sid_split_rid(&dom_sid, &rid);
+
+ return sid_check_is_unix_users(&dom_sid);
+}
+
+const char *unix_users_domain_name(void)
+{
+ return "Unix User";
+}
+
+BOOL lookup_unix_user_name(const char *name, DOM_SID *sid)
+{
+ struct passwd *pwd;
+
+ pwd = getpwnam_alloc(NULL, name);
+ if (pwd == NULL) {
+ return False;
+ }
+
+ sid_copy(sid, &global_sid_Unix_Users);
+ sid_append_rid(sid, pwd->pw_uid); /* For 64-bit uid's we have enough
+ * space ... */
+ talloc_free(pwd);
+ return True;
+}
+
+BOOL sid_check_is_unix_groups(const DOM_SID *sid)
+{
+ return sid_equal(sid, &global_sid_Unix_Groups);
+}
+
+BOOL sid_check_is_in_unix_groups(const DOM_SID *sid)
+{
+ DOM_SID dom_sid;
+ uint32 rid;
+
+ sid_copy(&dom_sid, sid);
+ sid_split_rid(&dom_sid, &rid);
+
+ return sid_check_is_unix_groups(&dom_sid);
+}
+
+const char *unix_groups_domain_name(void)
+{
+ return "Unix Group";
+}
+
+BOOL lookup_unix_group_name(const char *name, DOM_SID *sid)
+{
+ struct group *grp;
+
+ grp = getgrnam(name);
+ if (grp == NULL) {
+ return False;
+ }
+
+ sid_copy(sid, &global_sid_Unix_Groups);
+ sid_append_rid(sid, grp->gr_gid); /* For 64-bit uid's we have enough
+ * space ... */
+ return True;
+}
diff --git a/source3/passdb/util_wellknown.c b/source3/passdb/util_wellknown.c
index 8caae3b2a0..be3cf37446 100644
--- a/source3/passdb/util_wellknown.c
+++ b/source3/passdb/util_wellknown.c
@@ -70,6 +70,21 @@ static struct sid_name_map_info special_domains[] = {
{ &global_sid_NT_Authority, "NT Authority", nt_authority_users },
{ NULL, NULL, NULL }};
+BOOL sid_check_is_wellknown_domain(const DOM_SID *sid, const char **name)
+{
+ int i;
+
+ for (i=0; special_domains[i].sid != NULL; i++) {
+ if (sid_equal(sid, special_domains[i].sid)) {
+ if (name != NULL) {
+ *name = special_domains[i].name;
+ }
+ return True;
+ }
+ }
+ return False;
+}
+
/**************************************************************************
Looks up a known username from one of the known domains.
***************************************************************************/