r5965: Apply Volker's patch for "ldapsam trusted = yes" for samr_lookup_rids. Gives us
authorJim McDonough <jmcd@samba.org>
Tue, 22 Mar 2005 20:50:29 +0000 (20:50 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:56:13 +0000 (10:56 -0500)
again up to ~6x improvement on group membership lookups.

source/include/passdb.h
source/passdb/pdb_interface.c
source/passdb/pdb_ldap.c
source/rpc_server/srv_samr_nt.c

index 5a70bb45a8cc24265e761d6d0de32215eb4cbdfd..ca65a4e5e8809c3d5497c65c6772cba069c270b7 100644 (file)
@@ -342,6 +342,14 @@ typedef struct pdb_context
                                               DOM_SID **aliases,
                                               int *num_aliases);
 
+       NTSTATUS (*pdb_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);
+
        void (*free_fn)(struct pdb_context **);
        
        TALLOC_CTX *mem_ctx;
@@ -440,6 +448,13 @@ typedef struct pdb_methods
                                           const DOM_SID *members,
                                           int num_members,
                                           DOM_SID **aliases, int *num);
+       NTSTATUS (*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);
 
        void *private_data;  /* Private data of some kind */
        
index 52357507397ccd0cc312e858f723bec245499f04..949ee83dcd7818a9fc48b3850e0e4f3b390f430d 100644 (file)
@@ -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;
 }
index afbd488b855f45171bd0161c3a8177769ef79a95..14c764f12fd58be83c72a42698c4bf0e99053f42 100644 (file)
@@ -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 */
 
index 19989838c79fecda43759c60a5cb98b25728ca58..001da3f3ea7258a93ae8c205628d771e7acc59c3 100644 (file)
@@ -1464,8 +1464,9 @@ NTSTATUS _samr_chgpasswd_user(pipes_struct *p, SAMR_Q_CHGPASSWD_USER *q_u, SAMR_
 makes a SAMR_R_LOOKUP_RIDS structure.
 ********************************************************************/
 
-static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, fstring names[],
-           UNIHDR **pp_hdr_name, UNISTR2 **pp_uni_name)
+static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names,
+                                 const char **names, UNIHDR **pp_hdr_name,
+                                 UNISTR2 **pp_uni_name)
 {
        uint32 i;
        UNIHDR *hdr_name=NULL;
@@ -1485,7 +1486,7 @@ static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, fstring nam
        }
 
        for (i = 0; i < num_names; i++) {
-               DEBUG(10, ("names[%d]:%s\n", i, names[i] ? names[i] : ""));
+               DEBUG(10, ("names[%d]:%s\n", i, *names[i] ? names[i] : ""));
                init_unistr2(&uni_name[i], names[i], UNI_FLAGS_NONE);
                init_uni_hdr(&hdr_name[i], &uni_name[i]);
        }
@@ -1502,16 +1503,13 @@ static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, fstring nam
 
 NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOKUP_RIDS *r_u)
 {
-       fstring group_names[MAX_SAM_ENTRIES];
-       uint32 *group_attrs = NULL;
+       const char **names;
+       uint32 *attrs = NULL;
        UNIHDR *hdr_name = NULL;
        UNISTR2 *uni_name = NULL;
        DOM_SID pol_sid;
        int num_rids = q_u->num_rids1;
-       int i;
        uint32 acc_granted;
-       BOOL have_mapped = False;
-       BOOL have_unmapped = False;
        
        r_u->status = NT_STATUS_OK;
 
@@ -1527,11 +1525,12 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       if (num_rids) {
-               if ((group_attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_rids )) == NULL)
-                       return NT_STATUS_NO_MEMORY;
-       }
+       names = TALLOC_ZERO_ARRAY(p->mem_ctx, const char *, num_rids);
+       attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_rids);
+
+       if ((num_rids != 0) && ((names == NULL) || (attrs == NULL)))
+               return NT_STATUS_NO_MEMORY;
+
        if (!sid_equal(&pol_sid, get_global_sam_sid())) {
                /* TODO: Sooner or later we need to look up BUILTIN rids as
                 * well. -- vl */
@@ -1539,44 +1538,17 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
        }
 
        become_root();  /* lookup_sid can require root privs */
-
-       for (i = 0; i < num_rids; i++) {
-               fstring tmpname;
-               fstring domname;
-               DOM_SID sid;
-               enum SID_NAME_USE type;
-
-               group_attrs[i] = SID_NAME_UNKNOWN;
-               *group_names[i] = '\0';
-
-               sid_copy(&sid, &pol_sid);
-               sid_append_rid(&sid, q_u->rid[i]);
-
-               if (lookup_sid(&sid, domname, tmpname, &type)) {
-                       group_attrs[i] = (uint32)type;
-                       fstrcpy(group_names[i],tmpname);
-                       DEBUG(5,("_samr_lookup_rids: %s:%d\n", group_names[i],
-                                group_attrs[i]));
-                       have_mapped = True;
-               } else {
-                       have_unmapped = True;
-               }
-       }
-
+       r_u->status = pdb_lookup_rids(p->mem_ctx, &pol_sid, num_rids, q_u->rid,
+                                     &names, &attrs);
        unbecome_root();
 
  done:
 
-       r_u->status = NT_STATUS_NONE_MAPPED;
-
-       if (have_mapped)
-               r_u->status =
-                       have_unmapped ? STATUS_SOME_UNMAPPED : NT_STATUS_OK;
-
-       if(!make_samr_lookup_rids(p->mem_ctx, num_rids, group_names, &hdr_name, &uni_name))
+       if(!make_samr_lookup_rids(p->mem_ctx, num_rids, names,
+                                 &hdr_name, &uni_name))
                return NT_STATUS_NO_MEMORY;
 
-       init_samr_r_lookup_rids(r_u, num_rids, hdr_name, uni_name, group_attrs);
+       init_samr_r_lookup_rids(r_u, num_rids, hdr_name, uni_name, attrs);
 
        DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__));