summaryrefslogtreecommitdiff
path: root/source3/passdb
diff options
context:
space:
mode:
authorJim McDonough <jmcd@samba.org>2005-03-22 20:50:29 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 10:56:13 -0500
commitcf7d098b2c1032b51b8f5d439b29c8d20d0991ee (patch)
tree4f6f35536b5ae5da595e5c4fde9a5ebf454b1dfc /source3/passdb
parent93e04e941e15034c8e7aa1faedc74ce536049153 (diff)
downloadsamba-cf7d098b2c1032b51b8f5d439b29c8d20d0991ee.tar.gz
samba-cf7d098b2c1032b51b8f5d439b29c8d20d0991ee.tar.bz2
samba-cf7d098b2c1032b51b8f5d439b29c8d20d0991ee.zip
r5965: Apply Volker's patch for "ldapsam trusted = yes" for samr_lookup_rids. Gives us
again up to ~6x improvement on group membership lookups. (This used to be commit e2117bcb09cbd21df3b6621c2794a006418c1d9e)
Diffstat (limited to 'source3/passdb')
-rw-r--r--source3/passdb/pdb_interface.c98
-rw-r--r--source3/passdb/pdb_ldap.c244
2 files changed, 327 insertions, 15 deletions
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c
index 5235750739..949ee83dcd 100644
--- a/source3/passdb/pdb_interface.c
+++ b/source3/passdb/pdb_interface.c
@@ -659,6 +659,26 @@ static NTSTATUS context_enum_alias_memberships(struct pdb_context *context,
num_members, aliases, num);
}
+static NTSTATUS context_lookup_rids(struct pdb_context *context,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ int num_rids,
+ uint32 *rids,
+ const char ***names,
+ uint32 **attrs)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ return context->pdb_methods->lookup_rids(context->pdb_methods,
+ mem_ctx, domain_sid, num_rids,
+ rids, names, attrs);
+}
+
/******************************************************************
Free and cleanup a pdb context, any associated data and anything
that the attached modules might have associated.
@@ -788,6 +808,7 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
(*context)->pdb_del_aliasmem = context_del_aliasmem;
(*context)->pdb_enum_aliasmem = context_enum_aliasmem;
(*context)->pdb_enum_alias_memberships = context_enum_alias_memberships;
+ (*context)->pdb_lookup_rids = context_lookup_rids;
(*context)->free_fn = free_pdb_context;
@@ -1267,6 +1288,23 @@ BOOL pdb_enum_alias_memberships(const DOM_SID *members, int num_members,
aliases, num));
}
+NTSTATUS pdb_lookup_rids(TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ int num_rids,
+ uint32 *rids,
+ const char ***names,
+ uint32 **attrs)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
+ return pdb_context->pdb_lookup_rids(pdb_context, mem_ctx, domain_sid,
+ num_rids, rids, names, attrs);
+}
+
/***************************************************************
Initialize the static context (at smbd startup etc).
@@ -1439,6 +1477,65 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
return NT_STATUS_OK;
}
+NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ int num_rids,
+ uint32 *rids,
+ const char ***names,
+ uint32 **attrs)
+{
+ int i;
+ NTSTATUS result;
+ BOOL have_mapped = False;
+ BOOL have_unmapped = False;
+
+ (*names) = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids);
+ (*attrs) = TALLOC_ZERO_ARRAY(mem_ctx, uint32, num_rids);
+
+ if ((num_rids != 0) && (((*names) == NULL) || ((*attrs) == NULL)))
+ return NT_STATUS_NO_MEMORY;
+
+ if (!sid_equal(domain_sid, get_global_sam_sid())) {
+ /* TODO: Sooner or later we need to look up BUILTIN rids as
+ * well. -- vl */
+ goto done;
+ }
+
+ for (i = 0; i < num_rids; i++) {
+ fstring tmpname;
+ fstring domname;
+ DOM_SID sid;
+ enum SID_NAME_USE type;
+
+ (*attrs)[i] = SID_NAME_UNKNOWN;
+
+ sid_copy(&sid, domain_sid);
+ sid_append_rid(&sid, rids[i]);
+
+ if (lookup_sid(&sid, domname, tmpname, &type)) {
+ (*attrs)[i] = (uint32)type;
+ (*names)[i] = talloc_strdup(mem_ctx, tmpname);
+ if ((*names)[i] == NULL)
+ return NT_STATUS_NO_MEMORY;
+ DEBUG(5,("lookup_rids: %s:%d\n", (*names)[i],
+ (*attrs)[i]));
+ have_mapped = True;
+ } else {
+ have_unmapped = True;
+ }
+ }
+
+ done:
+
+ result = NT_STATUS_NONE_MAPPED;
+
+ if (have_mapped)
+ result = have_unmapped ? STATUS_SOME_UNMAPPED : NT_STATUS_OK;
+
+ return result;
+}
+
NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
{
*methods = TALLOC_P(mem_ctx, struct pdb_methods);
@@ -1478,6 +1575,7 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
(*methods)->del_aliasmem = pdb_default_del_aliasmem;
(*methods)->enum_aliasmem = pdb_default_enum_aliasmem;
(*methods)->enum_alias_memberships = pdb_default_alias_memberships;
+ (*methods)->lookup_rids = pdb_default_lookup_rids;
return NT_STATUS_OK;
}
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index afbd488b85..14c764f12f 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -2208,6 +2208,39 @@ static void add_rid_to_array_unique(TALLOC_CTX *mem_ctx,
*num += 1;
}
+static BOOL ldapsam_extract_rid_from_entry(LDAP *ldap_struct,
+ LDAPMessage *entry,
+ const DOM_SID *domain_sid,
+ uint32 *rid)
+{
+ fstring str;
+ DOM_SID sid;
+
+ if (!smbldap_get_single_attribute(ldap_struct, entry, "sambaSID",
+ str, sizeof(str)-1)) {
+ DEBUG(10, ("Could not find sambaSID attribute\n"));
+ return False;
+ }
+
+ if (!string_to_sid(&sid, str)) {
+ DEBUG(10, ("Could not convert string %s to sid\n", str));
+ return False;
+ }
+
+ if (sid_compare_domain(&sid, domain_sid) != 0) {
+ DEBUG(10, ("SID %s is not in expected domain %s\n",
+ str, sid_string_static(domain_sid)));
+ return False;
+ }
+
+ if (!sid_peek_rid(&sid, rid)) {
+ DEBUG(10, ("Could not peek into RID\n"));
+ return False;
+ }
+
+ return True;
+}
+
static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
TALLOC_CTX *mem_ctx,
const DOM_SID *group,
@@ -2254,26 +2287,16 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
entry != NULL;
entry = ldap_next_entry(conn->ldap_struct, entry))
{
- fstring str;
- DOM_SID sid;
uint32 rid;
- if (!smbldap_get_single_attribute(conn->ldap_struct,
- entry, "sambaSID",
- str, sizeof(str)-1))
- continue;
-
- if (!string_to_sid(&sid, str))
- goto done;
-
- if (!sid_check_is_in_our_domain(&sid)) {
- DEBUG(1, ("Inconsistent SAM -- group member uid not "
- "in our domain\n"));
+ if (!ldapsam_extract_rid_from_entry(conn->ldap_struct,
+ entry,
+ get_global_sam_sid(),
+ &rid)) {
+ DEBUG(2, ("Could not find sid from ldap entry\n"));
continue;
}
- sid_peek_rid(&sid, &rid);
-
add_rid_to_array_unique(mem_ctx, rid, member_rids,
num_members);
}
@@ -3112,6 +3135,196 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
return NT_STATUS_OK;
}
+static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ int num_rids,
+ uint32 *rids,
+ const char ***names,
+ uint32 **attrs)
+{
+ 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;
+
+ if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
+ return pdb_default_lookup_rids(methods, mem_ctx, domain_sid,
+ num_rids, rids, names, attrs);
+
+ if (!sid_equal(domain_sid, get_global_sam_sid())) {
+ /* TODO: Sooner or later we need to look up BUILTIN rids as
+ * well. -- vl */
+ goto done;
+ }
+
+ (*names) = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids);
+ (*attrs) = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
+
+ if ((num_rids != 0) && (((*names) == NULL) || ((*attrs) == NULL)))
+ return NT_STATUS_NO_MEMORY;
+
+ for (i=0; i<num_rids; i++)
+ (*attrs)[i] = SID_NAME_UNKNOWN;
+
+ allsids = strdup("");
+ if (allsids == NULL) return NT_STATUS_NO_MEMORY;
+
+ 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);
+ }
+
+ /* First look for users */
+
+ {
+ char *filter;
+ const char *ldap_attrs[] = { "uid", "sambaSid", NULL };
+
+ asprintf(&filter, ("(&(objectClass=sambaSamAccount)(|%s))"),
+ allsids);
+ if (filter == NULL) return NT_STATUS_NO_MEMORY;
+
+ rc = smbldap_search(ldap_state->smbldap_state,
+ lp_ldap_user_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
+ &msg);
+
+ SAFE_FREE(filter);
+ }
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ num_mapped = 0;
+
+ for (entry = ldap_first_entry(ldap_struct, msg);
+ entry != NULL;
+ entry = ldap_next_entry(ldap_struct, entry))
+ {
+ uint32 rid;
+ int rid_index;
+ fstring str;
+
+ if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
+ get_global_sam_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)) {
+ DEBUG(2, ("Could not retrieve uid attribute\n"));
+ continue;
+ }
+
+ for (rid_index = 0; rid_index < num_rids; rid_index++) {
+ if (rid == rids[rid_index])
+ break;
+ }
+
+ if (rid_index == num_rids) {
+ DEBUG(2, ("Got a RID not asked for: %d\n", rid));
+ continue;
+ }
+
+ (*attrs)[rid_index] = SID_NAME_USER;
+ (*names)[rid_index] = talloc_strdup(mem_ctx, str);
+ if ((*names)[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
+
+ num_mapped += 1;
+ }
+
+ if (num_mapped == num_rids) {
+ /* No need to look for groups anymore -- we're done */
+ result = NT_STATUS_OK;
+ goto done;
+ }
+
+ /* Same game for groups */
+
+ {
+ char *filter;
+ const char *ldap_attrs[] = { "cn", "sambaSid", NULL };
+
+ asprintf(&filter, ("(&(objectClass=sambaGroupMapping)(|%s))"),
+ allsids);
+ if (filter == NULL) return NT_STATUS_NO_MEMORY;
+
+ rc = smbldap_search(ldap_state->smbldap_state,
+ lp_ldap_group_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
+ &msg);
+
+ SAFE_FREE(filter);
+ }
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ for (entry = ldap_first_entry(ldap_struct, msg);
+ entry != NULL;
+ entry = ldap_next_entry(ldap_struct, entry))
+ {
+ uint32 rid;
+ int rid_index;
+ fstring str;
+
+ if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
+ get_global_sam_sid(),
+ &rid)) {
+ DEBUG(2, ("Could not find sid from ldap entry\n"));
+ continue;
+ }
+
+ if (!smbldap_get_single_attribute(ldap_struct, entry,
+ "cn", str, sizeof(str)-1)) {
+ DEBUG(2, ("Could not retrieve cn attribute\n"));
+ continue;
+ }
+
+ for (rid_index = 0; rid_index < num_rids; rid_index++) {
+ if (rid == rids[rid_index])
+ break;
+ }
+
+ if (rid_index == num_rids) {
+ DEBUG(2, ("Got a RID not asked for: %d\n", rid));
+ continue;
+ }
+
+ (*attrs)[rid_index] = SID_NAME_DOM_GRP;
+ (*names)[rid_index] = talloc_strdup(mem_ctx, str);
+ if ((*names)[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
+ num_mapped += 1;
+ }
+
+ result = NT_STATUS_NONE_MAPPED;
+
+ if (num_mapped > 0)
+ result = (num_mapped == num_rids) ?
+ NT_STATUS_OK : STATUS_SOME_UNMAPPED;
+ done:
+ SAFE_FREE(allsids);
+
+ if (msg != NULL)
+ ldap_msgfree(msg);
+
+ return result;
+}
+
/**********************************************************************
Housekeeping
*********************************************************************/
@@ -3169,6 +3382,7 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **
(*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;
/* TODO: Setup private data and free */