s4:samr Push most of samr_QueryGroupMember into a helper function
authorAndrew Bartlett <abartlet@samba.org>
Thu, 20 May 2010 22:42:21 +0000 (08:42 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 24 May 2010 13:08:49 +0000 (23:08 +1000)
This is a rewrite of the group membership lookup code, using the
stored extended DNs to avoid doing the lookup into each member to find
the SID

By splitting this out, the logic is able to be shared, rather than
copied, into a passdb wrapper.

Andrew Bartlett

source4/dsdb/common/util_samr.c
source4/rpc_server/samr/dcesrv_samr.c

index 58d5b3fd2158fcbad9f322f47051da289d6eab87..3faf513e37b2edfe3413780aeeb862b54d995fa6 100644 (file)
@@ -399,3 +399,70 @@ NTSTATUS dsdb_add_domain_alias(struct ldb_context *ldb,
        return NT_STATUS_OK;
 }
 
+/* Return the members of this group (which may be a domain group or an alias) */
+NTSTATUS dsdb_enum_group_mem(struct ldb_context *ldb,
+                            TALLOC_CTX *mem_ctx,
+                            struct ldb_dn *dn,
+                            struct dom_sid **members_out,
+                            size_t *pnum_members)
+{
+       struct ldb_message *msg;
+       int i, ret;
+       struct dom_sid *members;
+       struct ldb_message_element *member_el;
+       const char *attrs[] = { "member", NULL };
+       NTSTATUS status;
+       TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+       NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+       ret = dsdb_search_one(ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs,
+                             DSDB_SEARCH_SHOW_EXTENDED_DN, NULL);
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               talloc_free(tmp_ctx);
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+       if (ret != LDB_SUCCESS) {
+               DEBUG(1, ("dsdb_enum_group_mem: dsdb_search for %s failed: %s\n",
+                         ldb_dn_get_linearized(dn), ldb_errstring(ldb)));
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       member_el = ldb_msg_find_element(msg, "member");
+       if (!member_el) {
+               *members_out = NULL;
+               *pnum_members = 0;
+               talloc_free(tmp_ctx);
+               return NT_STATUS_OK;
+       }
+
+       members = talloc_array(mem_ctx, struct dom_sid, member_el->num_values);
+       if (members == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0; i <member_el->num_values; i++) {
+               struct ldb_dn *member_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb,
+                                                              &member_el->values[i]);
+               if (!member_dn || !ldb_dn_validate(member_dn)) {
+                       DEBUG(1, ("Could not parse %*.*s as a DN\n",
+                                 (int)member_el->values[i].length,
+                                 (int)member_el->values[i].length,
+                                 (const char *)member_el->values[i].data));
+                       talloc_free(tmp_ctx);
+                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               }
+
+               status = dsdb_get_extended_dn_sid(member_dn, &members[i], "SID");
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(1, ("Could find SID attribute on extended DN %s\n",
+                                 ldb_dn_get_extended_linearized(tmp_ctx, dn, 1)));
+                       talloc_free(tmp_ctx);
+                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               }
+       }
+
+       *members_out = talloc_steal(mem_ctx, members);
+       *pnum_members = member_el->num_values;
+       talloc_free(tmp_ctx);
+       return NT_STATUS_OK;
+}
index 1e5686ae7248baa660d382acba1203930b2a1709..0fef07a9096ba6ed4335fa66d9dd14051e6a6b88 100644 (file)
@@ -2145,68 +2145,58 @@ static NTSTATUS dcesrv_samr_DeleteGroupMember(struct dcesrv_call_state *dce_call
 static NTSTATUS dcesrv_samr_QueryGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                      struct samr_QueryGroupMember *r)
 {
+       NTSTATUS status;
        struct dcesrv_handle *h;
        struct samr_account_state *a_state;
-       struct ldb_message **res;
-       struct ldb_message_element *el;
        struct samr_RidTypeArray *array;
-       const char * const attrs[2] = { "member", NULL };
-       int ret;
+       size_t i;
+       struct dom_sid *members_as_sids;
+       size_t num_members;
+       struct dom_sid *dom_sid;
 
        DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
 
        a_state = h->data;
 
-       /* pull the member attribute */
-       ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
-                             a_state->account_dn, &res, attrs);
+       dom_sid = a_state->domain_state->domain_sid;
+       status = dsdb_enum_group_mem(a_state->sam_ctx, mem_ctx, a_state->account_dn, &members_as_sids, &num_members);
 
-       if (ret != 1) {
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
-       array = talloc(mem_ctx, struct samr_RidTypeArray);
+       array = talloc_zero(mem_ctx, struct samr_RidTypeArray);
 
        if (array == NULL)
                return NT_STATUS_NO_MEMORY;
 
-       ZERO_STRUCTP(array);
-
-       el = ldb_msg_find_element(res[0], "member");
-
-       if (el != NULL) {
-               unsigned int i;
-
-               array->count = el->num_values;
+       if (num_members == 0) {
+               *r->out.rids = array;
 
-               array->rids = talloc_array(mem_ctx, uint32_t,
-                                            el->num_values);
-               if (array->rids == NULL)
-                       return NT_STATUS_NO_MEMORY;
-
-               array->types = talloc_array(mem_ctx, uint32_t,
-                                           el->num_values);
-               if (array->types == NULL)
-                       return NT_STATUS_NO_MEMORY;
-
-               for (i=0; i<el->num_values; i++) {
-                       struct ldb_message **res2;
-                       const char * const attrs2[2] = { "objectSid", NULL };
-                       ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
-                                          ldb_dn_from_ldb_val(mem_ctx, a_state->sam_ctx, &el->values[i]),
-                                          &res2, attrs2);
-                       if (ret != 1)
-                               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               return NT_STATUS_OK;
+       }
 
-                       array->rids[i] =
-                               samdb_result_rid_from_sid(mem_ctx, res2[0],
-                                                         "objectSid", 0);
+       array->count = 0;
+       array->rids = talloc_array(array, uint32_t,
+                                  num_members);
+       if (array->rids == NULL)
+               return NT_STATUS_NO_MEMORY;
 
-                       if (array->rids[i] == 0)
-                               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       array->types = talloc_array(array, uint32_t,
+                                   num_members);
+       if (array->types == NULL)
+               return NT_STATUS_NO_MEMORY;
 
-                       array->types[i] = 7; /* RID type of some kind, not sure what the value means. */
+       for (i=0; i<num_members; i++) {
+               if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
+                       continue;
                }
+               status = dom_sid_split_rid(NULL, &members_as_sids[i], NULL, &array->rids[array->count]);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+               array->types[array->count] = 7; /* RID type of some kind, not sure what the value means. */
+               array->count++;
        }
 
        *r->out.rids = array;
@@ -2561,60 +2551,43 @@ static NTSTATUS dcesrv_samr_GetMembersInAlias(struct dcesrv_call_state *dce_call
        struct dcesrv_handle *h;
        struct samr_account_state *a_state;
        struct samr_domain_state *d_state;
-       struct ldb_message **msgs;
        struct lsa_SidPtr *sids;
-       struct ldb_message_element *el;
-       const char * const attrs[2] = { "member", NULL};
-       int ret;
-
+       size_t i;
+       struct dom_sid *members;
+       size_t num_members;
+       NTSTATUS status;
        DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
 
        a_state = h->data;
        d_state = a_state->domain_state;
 
-       ret = gendb_search_dn(d_state->sam_ctx, mem_ctx,
-                             a_state->account_dn, &msgs, attrs);
-
-       if (ret == -1) {
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       } else if (ret == 0) {
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       } else if (ret != 1) {
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       status = dsdb_enum_group_mem(d_state->sam_ctx, mem_ctx,
+                                    a_state->account_dn, &members, &num_members);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
-       r->out.sids->num_sids = 0;
        r->out.sids->sids = NULL;
 
-       el = ldb_msg_find_element(msgs[0], "member");
-
-       if (el != NULL) {
-               unsigned int i;
-
-               sids = talloc_array(mem_ctx, struct lsa_SidPtr,
-                                     el->num_values);
+       if (num_members == 0) {
+               return NT_STATUS_OK;
+       }
 
-               if (sids == NULL)
-                       return NT_STATUS_NO_MEMORY;
+       sids = talloc_array(mem_ctx, struct lsa_SidPtr,
+                           num_members);
 
-               for (i=0; i<el->num_values; i++) {
-                       struct ldb_message **msgs2;
-                       const char * const attrs2[2] = { "objectSid", NULL };
-                       ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
-                                             ldb_dn_from_ldb_val(mem_ctx, a_state->sam_ctx, &el->values[i]),
-                                             &msgs2, attrs2);
-                       if (ret != 1)
-                               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       if (sids == NULL)
+               return NT_STATUS_NO_MEMORY;
 
-                       sids[i].sid = samdb_result_dom_sid(mem_ctx, msgs2[0],
-                                                          "objectSid");
+       for (i=0; i<num_members; i++) {
 
-                       if (sids[i].sid == NULL)
-                               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               sids[i].sid = dom_sid_dup(sids, &members[i]);
+               if (sids[i].sid == NULL) {
+                       return NT_STATUS_NO_MEMORY;
                }
-               r->out.sids->num_sids = el->num_values;
-               r->out.sids->sids = sids;
        }
+       r->out.sids->num_sids = num_members;
+       r->out.sids->sids = sids;
 
        return NT_STATUS_OK;
 }