Author: obnox
Date: 2007-05-30 22:57:46 +0000 (Wed, 30 May 2007)
New Revision: 23255

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=23255

Log:
Merge the reworking of winbindd_ads lookup_groupmem function
from 3_0: Call lsa_lookup_sids on the list of sids that
can not be resolved from cache, instead of passing each
single sid to dn_lookup (which becomes obsoleten and is
removed). Weed out the sids that could not be resolved.

This merges r23072, r23078, r23252, r23253.

Michael


Modified:
   branches/SAMBA_3_0_26/source/nsswitch/winbindd_ads.c


Changeset:
Modified: branches/SAMBA_3_0_26/source/nsswitch/winbindd_ads.c
===================================================================
--- branches/SAMBA_3_0_26/source/nsswitch/winbindd_ads.c        2007-05-30 
22:43:11 UTC (rev 23254)
+++ branches/SAMBA_3_0_26/source/nsswitch/winbindd_ads.c        2007-05-30 
22:57:46 UTC (rev 23255)
@@ -402,50 +402,11 @@
        return NT_STATUS_OK;
 }
 
-/* convert a DN to a name, SID and name type 
-   this might become a major speed bottleneck if groups have
-   lots of users, in which case we could cache the results
-*/
-static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
-                     const char *dn,
-                     char **name, uint32 *name_type, DOM_SID *sid)
-{
-       LDAPMessage *res = NULL;
-       const char *attrs[] = {"userPrincipalName", "sAMAccountName",
-                              "objectSid", "sAMAccountType", NULL};
-       ADS_STATUS rc;
-       uint32 atype;
-       DEBUG(3,("ads: dn_lookup\n"));
+/* If you are looking for "dn_lookup": Yes, it used to be here!
+ * It has gone now since it was a major speed bottleneck in
+ * lookup_groupmem (its only use). It has been replaced by
+ * an rpc lookup sids call... R.I.P. */
 
-       rc = ads_search_retry_dn(ads, &res, dn, attrs);
-
-       if (!ADS_ERR_OK(rc) || !res) {
-               goto failed;
-       }
-
-       (*name) = ads_pull_username(ads, mem_ctx, res);
-
-       if (!ads_pull_uint32(ads, res, "sAMAccountType", &atype)) {
-               goto failed;
-       }
-       (*name_type) = ads_atype_map(atype);
-
-       if (!ads_pull_sid(ads, res, "objectSid", sid)) {
-               goto failed;
-       }
-
-       if (res) 
-               ads_msgfree(ads, res);
-
-       return True;
-
-failed:
-       if (res) 
-               ads_msgfree(ads, res);
-
-       return False;
-}
-
 /* Lookup user information from a rid */
 static NTSTATUS query_user(struct winbindd_domain *domain, 
                           TALLOC_CTX *mem_ctx, 
@@ -942,12 +903,19 @@
        char *ldap_exp;
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
        char *sidstr;
-       char **members;
+       char **members = NULL;
        int i;
-       size_t num_members;
-       fstring sid_string;
+       size_t num_members = 0;
        ads_control args;
+        struct rpc_pipe_client *cli;
+        POLICY_HND lsa_policy;
+       DOM_SID *sid_mem_nocache = NULL;
+       char **names_nocache = NULL;
+       uint32 *name_types_nocache = NULL;
+       char **domains_nocache = NULL;     /* only needed for 
rpccli_lsa_lookup_sids */
+       uint32 num_nocache = 0;
 
+
        DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name, 
                  sid_string_static(group_sid)));
 
@@ -980,9 +948,6 @@
        }
        SAFE_FREE(sidstr);
 
-       members = NULL;
-       num_members = 0;
-
        args.control = ADS_EXTENDED_DN_OID;
        args.val = ADS_EXTENDED_DN_HEX_STRING;
        args.critical = True;
@@ -996,74 +961,135 @@
                goto done;
        } 
        
-       /* now we need to turn a list of members into rids, names and name 
types 
-          the problem is that the members are in the form of distinguised names
-       */
-
-       if (num_members) {
+       DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", 
num_members));
+       
+       /* Now that we have a list of sids, we need to get the
+        * lists of names and name_types belonging to these sids.
+        * even though conceptually not quite clean,  we use the 
+        * RPC call lsa_lookup_sids for this since it can handle a 
+        * list of sids. ldap calls can just resolve one sid at a time.
+        *
+        * At this stage, the sids are still hidden in the exetended dn
+        * member output format. We actually do a little better than
+        * stated above: In extracting the sids from the member strings,
+        * we try to resolve as many sids as possible from the
+        * cache. Only the rest is passed to the lsa_lookup_sids call. */
+       
+       if (num_names) {
                (*sid_mem) = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, num_members);
+               (*names) = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_members);
                (*name_types) = TALLOC_ZERO_ARRAY(mem_ctx, uint32, num_members);
-               (*names) = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_members);
+               (sid_mem_nocache) = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, 
num_members);
 
                if ((members == NULL) || (*sid_mem == NULL) ||
-                    (*name_types == NULL) || (*names == NULL)) {
+                   (*names == NULL) || (*name_types == NULL) ||
+                   (sid_mem_nocache == NULL))
+               {
                        DEBUG(1, ("talloc failed\n"));
                        status = NT_STATUS_NO_MEMORY;
                        goto done;
                }
-       } else {
+       }
+       else {
                (*sid_mem) = NULL;
+               (*names) = NULL;
                (*name_types) = NULL;
-               (*names) = NULL;
        }
- 
-       for (i=0;i<num_members;i++) {
+
+       for (i=0; i<num_members; i++) {
                uint32 name_type;
-               char *name, *domain_name, *dn;
+               char *name, *domain_name;
                DOM_SID sid;
 
-               if ((!ads_get_sid_from_extended_dn(mem_ctx, members[i], 
ADS_EXTENDED_DN_HEX_STRING, &sid)) ||
-                   (!ads_get_dn_from_extended_dn(mem_ctx, members[i], &dn)))
-               {
+               if (!ads_get_sid_from_extended_dn(mem_ctx, members[i], 
args.val, &sid)) {
                        status = NT_STATUS_INVALID_PARAMETER;
-                       goto done;
+                       goto done;
                }
-
                if (lookup_cached_sid(mem_ctx, &sid, &domain_name, &name, 
&name_type)) {
-
-                       DEBUG(10,("ads: lookup_groupmem: got sid %s from 
cache\n", 
-                               sid_string_static(&sid)));
-
+                       DEBUG(10,("ads: lookup_groupmem: got sid %s from 
cache\n",
+                                sid_string_static(&sid)));
+                       sid_copy(&(*sid_mem)[*num_names], &sid);
                        (*names)[*num_names] = CONST_DISCARD(char *,name);
                        (*name_types)[*num_names] = name_type;
-                       sid_copy(&(*sid_mem)[*num_names], &sid);
-
                        (*num_names)++;
-
-                       continue;
                }
+               else {
+                       DEBUG(10, ("ads: lookup_groupmem: sid %s not found in 
cache\n",
+                                 sid_string_static(&sid)));
+                       sid_copy(&(sid_mem_nocache)[num_nocache], &sid);
+                       num_nocache++;
+               }
+       }
 
-               if (dn_lookup(ads, mem_ctx, dn, &name, &name_type, &sid)) {
+       DEBUG(10, ("ads: lookup_groupmem: %d sids found in cache, "
+                 "%d left for lsa_lookupsids\n", *num_names, num_nocache));
 
-                       DEBUG(10,("ads: lookup_groupmem: got sid %s from 
dn_lookup\n", 
-                               sid_string_static(&sid)));
-                       
-                       (*names)[*num_names] = name;
-                       (*name_types)[*num_names] = name_type;
-                       sid_copy(&(*sid_mem)[*num_names], &sid);
-                       
-                       (*num_names)++;
+       /* handle sids not resolved from cache by lsa_lookup_sids */
+       if (num_nocache > 0) {
 
+               status = cm_connect_lsa(domain, mem_ctx, &cli, &lsa_policy);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto done;
                }
-       }       
 
+               status = rpccli_lsa_lookup_sids_all(cli, mem_ctx, 
+                                                   &lsa_policy,
+                                                   num_nocache, 
+                                                   sid_mem_nocache, 
+                                                   &domains_nocache, 
+                                                   &names_nocache, 
+                                                   &name_types_nocache);
+
+               if (NT_STATUS_IS_OK(status) ||
+                   NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) 
+               {
+                       /* Copy the entries over from the "_nocache" arrays 
+                        * to the result arrays, skipping the gaps the 
+                        * lookup_sids call left. */
+                       *num_names = 0;
+                       for (i=0; i < num_nocache; i++) {
+                               if (((names_nocache)[i] != NULL) && 
+                                   ((name_types_nocache)[i] != 
SID_NAME_UNKNOWN)) 
+                               {
+                                       sid_copy(&(*sid_mem)[*num_names],
+                                                &sid_mem_nocache[i]);
+                                       (*names)[*num_names] = names_nocache[i];
+                                       (*name_types)[*num_names] = 
name_types_nocache[i];
+                                       (*num_names)++;
+                               }
+                       }
+               }
+               else if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
+                       DEBUG(10, ("lookup_groupmem: lsa_lookup_sids could "
+                                  "not map any SIDs at all.\n"));
+                       /* Don't handle this as an error here.
+                        * There is nothing left to do with respect to the 
+                        * overall result... */
+               }
+               else if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(10, ("lookup_groupmem: Error looking up %d "
+                                  "sids via rpc_lsa_lookup_sids: %s\n",
+                                  num_members, nt_errstr(status)));
+                       goto done;
+               }
+       }
+
        status = NT_STATUS_OK;
-       DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n", 
sid_to_string(sid_string, group_sid)));
+       DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n",
+                sid_string_static(group_sid)));
+
 done:
 
        if (res) 
                ads_msgfree(ads, res);
 
+       /* free intermediate lists. - a temp talloc ctx might be better. */
+       TALLOC_FREE(sid_mem_nocache);
+       TALLOC_FREE(names_nocache);
+       TALLOC_FREE(name_types_nocache);
+       TALLOC_FREE(domains_nocache);
+
        return status;
 }
 

Reply via email to