diff options
-rw-r--r-- | source4/dsdb/common/util_samr.c | 67 | ||||
-rw-r--r-- | source4/rpc_server/samr/dcesrv_samr.c | 133 |
2 files changed, 120 insertions, 80 deletions
diff --git a/source4/dsdb/common/util_samr.c b/source4/dsdb/common/util_samr.c index 58d5b3fd21..3faf513e37 100644 --- a/source4/dsdb/common/util_samr.c +++ b/source4/dsdb/common/util_samr.c @@ -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; +} diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index 1e5686ae72..0fef07a909 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -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; } |