auth/credentials: don't ignore "client use kerberos" and --use-kerberos for machine...
[samba.git] / source3 / winbindd / wb_group_members.c
index a7eb9ba437a56f78fc44b1ac5eee0cecf9341948..3fe7357e8b7b82ea9ef39536f39e7911784b636e 100644 (file)
 
 #include "includes.h"
 #include "winbindd.h"
-#include "librpc/gen_ndr/cli_wbint.h"
+#include "librpc/gen_ndr/ndr_winbind_c.h"
+#include "../librpc/gen_ndr/ndr_security.h"
+#include "../libcli/security/security.h"
+#include "lib/util/util_tdb.h"
+#include "lib/dbwrap/dbwrap.h"
+#include "lib/dbwrap/dbwrap_rbt.h"
 
 /*
  * We have 3 sets of routines here:
@@ -70,8 +75,8 @@ static struct tevent_req *wb_lookupgroupmem_send(TALLOC_CTX *mem_ctx,
                return tevent_req_post(req, ev);
        }
 
-       subreq = rpccli_wbint_LookupGroupMembers_send(
-               state, ev, domain->child.rpccli, &state->sid, type,
+       subreq = dcerpc_wbint_LookupGroupMembers_send(
+               state, ev, dom_child_handle(domain), &state->sid, type,
                &state->members);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
@@ -88,23 +93,19 @@ static void wb_lookupgroupmem_done(struct tevent_req *subreq)
                req, struct wb_lookupgroupmem_state);
        NTSTATUS status, result;
 
-       status = rpccli_wbint_LookupGroupMembers_recv(subreq, state, &result);
+       status = dcerpc_wbint_LookupGroupMembers_recv(subreq, state, &result);
        TALLOC_FREE(subreq);
-       if (!NT_STATUS_IS_OK(status)) {
+       if (any_nt_status_not_ok(status, result, &status)) {
                tevent_req_nterror(req, status);
                return;
        }
-       if (!NT_STATUS_IS_OK(result)) {
-               tevent_req_nterror(req, result);
-               return;
-       }
        tevent_req_done(req);
 }
 
 static NTSTATUS wb_lookupgroupmem_recv(struct tevent_req *req,
-                                          TALLOC_CTX *mem_ctx,
-                                          int *num_members,
-                                          struct wbint_Principal **members)
+                                      TALLOC_CTX *mem_ctx,
+                                      uint32_t *num_members,
+                                      struct wbint_Principal **members)
 {
        struct wb_lookupgroupmem_state *state = tevent_req_data(
                req, struct wb_lookupgroupmem_state);
@@ -126,8 +127,8 @@ static NTSTATUS wb_lookupgroupmem_recv(struct tevent_req *req,
 struct wb_groups_members_state {
        struct tevent_context *ev;
        struct wbint_Principal *groups;
-       int num_groups;
-       int next_group;
+       uint32_t num_groups;
+       uint32_t next_group;
        struct wbint_Principal *all_members;
 };
 
@@ -138,10 +139,10 @@ static void wb_groups_members_done(struct tevent_req *subreq);
 
 static struct tevent_req *wb_groups_members_send(TALLOC_CTX *mem_ctx,
                                                 struct tevent_context *ev,
-                                                int num_groups,
+                                                uint32_t num_groups,
                                                 struct wbint_Principal *groups)
 {
-       struct tevent_req *req, *subreq;
+       struct tevent_req *req, *subreq = NULL;
        struct wb_groups_members_state *state;
        NTSTATUS status;
 
@@ -156,9 +157,9 @@ static struct tevent_req *wb_groups_members_send(TALLOC_CTX *mem_ctx,
        state->next_group = 0;
        state->all_members = NULL;
 
+       D_DEBUG("Looking up %"PRIu32" group(s).\n", num_groups);
        status = wb_groups_members_next_subreq(state, state, &subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
+       if (tevent_req_nterror(req, status)) {
                return tevent_req_post(req, ev);
        }
        if (subreq == NULL) {
@@ -198,27 +199,34 @@ static void wb_groups_members_done(struct tevent_req *subreq)
                subreq, struct tevent_req);
        struct wb_groups_members_state *state = tevent_req_data(
                req, struct wb_groups_members_state);
-       int i, num_all_members;
-       int num_members = 0;
+       uint32_t i, num_all_members;
+       uint32_t num_members = 0;
        struct wbint_Principal *members = NULL;
        NTSTATUS status;
 
-       status = wb_lookupgroupmem_recv(subreq, state, &num_members,
-                                           &members);
+       status = wb_lookupgroupmem_recv(subreq, state, &num_members, &members);
        TALLOC_FREE(subreq);
 
        /*
         * In this error handling here we might have to be a bit more generous
-        * and just continue if an error occured.
+        * and just continue if an error occurred.
         */
 
        if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
-               return;
+               if (!NT_STATUS_EQUAL(
+                           status, NT_STATUS_TRUSTED_DOMAIN_FAILURE)) {
+                       tevent_req_nterror(req, status);
+                       return;
+               }
+               num_members = 0;
        }
 
        num_all_members = talloc_array_length(state->all_members);
 
+       D_DEBUG("Adding %"PRIu32" new member(s) to existing %"PRIu32" member(s)\n",
+               num_members,
+               num_all_members);
+
        state->all_members = talloc_realloc(
                state, state->all_members, struct wbint_Principal,
                num_all_members + num_members);
@@ -237,8 +245,7 @@ static void wb_groups_members_done(struct tevent_req *subreq)
        TALLOC_FREE(members);
 
        status = wb_groups_members_next_subreq(state, state, &subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
+       if (tevent_req_nterror(req, status)) {
                return;
        }
        if (subreq == NULL) {
@@ -250,7 +257,7 @@ static void wb_groups_members_done(struct tevent_req *subreq)
 
 static NTSTATUS wb_groups_members_recv(struct tevent_req *req,
                                       TALLOC_CTX *mem_ctx,
-                                      int *num_members,
+                                      uint32_t *num_members,
                                       struct wbint_Principal **members)
 {
        struct wb_groups_members_state *state = tevent_req_data(
@@ -268,14 +275,14 @@ static NTSTATUS wb_groups_members_recv(struct tevent_req *req,
 
 /*
  * This is the routine expanding a list of groups up to a certain level. We
- * collect the users in a talloc_dict: We have to add them without duplicates,
- * and and talloc_dict is an indexed (here indexed by SID) data structure.
+ * collect the users in a rbt database: We have to add them without duplicates,
+ * and the db is indexed by SID.
  */
 
 struct wb_group_members_state {
        struct tevent_context *ev;
        int depth;
-       struct talloc_dict *users;
+       struct db_context *users;
        struct wbint_Principal *groups;
 };
 
@@ -287,36 +294,48 @@ static void wb_group_members_done(struct tevent_req *subreq);
 struct tevent_req *wb_group_members_send(TALLOC_CTX *mem_ctx,
                                         struct tevent_context *ev,
                                         const struct dom_sid *sid,
-                                        enum lsa_SidType type,
+                                        uint32_t num_sids,
+                                        enum lsa_SidType *type,
                                         int max_depth)
 {
-       struct tevent_req *req, *subreq;
+       struct tevent_req *req, *subreq = NULL;
        struct wb_group_members_state *state;
        NTSTATUS status;
+       struct dom_sid_buf buf;
+       uint32_t i;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct wb_group_members_state);
        if (req == NULL) {
                return NULL;
        }
+       D_INFO("WB command group_members start (max_depth=%d).\n", max_depth);
+       for (i = 0; i < num_sids; i++) {
+               D_INFO("Looking up members of group SID %s with SID type %d\n",
+                      dom_sid_str_buf(&sid[i], &buf),
+                      type[i]);
+       }
+
        state->ev = ev;
        state->depth = max_depth;
-       state->users = talloc_dict_init(state);
+       state->users = db_open_rbt(state);
        if (tevent_req_nomem(state->users, req)) {
                return tevent_req_post(req, ev);
        }
 
-       state->groups = talloc(state, struct wbint_Principal);
+       state->groups = talloc_array(state, struct wbint_Principal, num_sids);
        if (tevent_req_nomem(state->groups, req)) {
                return tevent_req_post(req, ev);
        }
-       state->groups->name = NULL;
-       sid_copy(&state->groups->sid, sid);
-       state->groups->type = type;
+
+       for (i = 0; i < num_sids; i++) {
+               state->groups[i].name = NULL;
+               sid_copy(&state->groups[i].sid, &sid[i]);
+               state->groups[i].type = type[i];
+       }
 
        status = wb_group_members_next_subreq(state, state, &subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
+       if (tevent_req_nterror(req, status)) {
                return tevent_req_post(req, ev);
        }
        if (subreq == NULL) {
@@ -336,10 +355,12 @@ static NTSTATUS wb_group_members_next_subreq(
        if ((talloc_array_length(state->groups) == 0)
            || (state->depth <= 0)) {
                *psubreq = NULL;
+               D_DEBUG("Finished. The depth is %d.\n", state->depth);
                return NT_STATUS_OK;
        }
        state->depth -= 1;
 
+       D_DEBUG("The depth is decremented to %d.\n", state->depth);
        subreq = wb_groups_members_send(
                mem_ctx, state->ev, talloc_array_length(state->groups),
                state->groups);
@@ -350,25 +371,38 @@ static NTSTATUS wb_group_members_next_subreq(
        return NT_STATUS_OK;
 }
 
+NTSTATUS add_member_to_db(struct db_context *db, struct dom_sid *sid,
+                         const char *name)
+{
+       size_t len = ndr_size_dom_sid(sid, 0);
+       uint8_t sidbuf[len];
+       TDB_DATA key = { .dptr = sidbuf, .dsize = sizeof(sidbuf) };
+       NTSTATUS status;
+
+       sid_linearize(sidbuf, sizeof(sidbuf), sid);
+
+       status = dbwrap_store(db, key, string_term_tdb_data(name), 0);
+       return status;
+}
+
 static void wb_group_members_done(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
                subreq, struct tevent_req);
        struct wb_group_members_state *state = tevent_req_data(
                req, struct wb_group_members_state);
-       int i, num_groups, new_users, new_groups;
-       int num_members = 0;
+       uint32_t i, num_groups, new_groups;
+       uint32_t num_members = 0;
        struct wbint_Principal *members = NULL;
        NTSTATUS status;
 
        status = wb_groups_members_recv(subreq, state, &num_members, &members);
        TALLOC_FREE(subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
+       if (tevent_req_nterror(req, status)) {
                return;
        }
 
-       new_users = new_groups = 0;
+       new_groups = 0;
        for (i=0; i<num_members; i++) {
                switch (members[i].type) {
                case SID_NAME_DOM_GRP:
@@ -399,26 +433,12 @@ static void wb_group_members_done(struct tevent_req *subreq)
                        /*
                         * Add a copy of members[i] to state->users
                         */
-                       struct wbint_Principal *m;
-                       struct dom_sid *sid;
-                       DATA_BLOB key;
-
-                       m = talloc(talloc_tos(), struct wbint_Principal);
-                       if (tevent_req_nomem(m, req)) {
+                       status = add_member_to_db(state->users, &members[i].sid,
+                                                 members[i].name);
+                       if (tevent_req_nterror(req, status)) {
                                return;
                        }
-                       sid_copy(&m->sid, &members[i].sid);
-                       m->name = talloc_move(m, &members[i].name);
-                       m->type = members[i].type;
-
-                       sid = &members[i].sid;
-                       key = data_blob_const(
-                               sid, ndr_size_dom_sid(sid, NULL, 0));
 
-                       if (!talloc_dict_set(state->users, key, &m)) {
-                               tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
-                               return;
-                       }
                        break;
                }
                case SID_NAME_DOM_GRP:
@@ -442,8 +462,7 @@ static void wb_group_members_done(struct tevent_req *subreq)
        }
 
        status = wb_group_members_next_subreq(state, state, &subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
+       if (tevent_req_nterror(req, status)) {
                return;
        }
        if (subreq == NULL) {
@@ -454,13 +473,15 @@ static void wb_group_members_done(struct tevent_req *subreq)
 }
 
 NTSTATUS wb_group_members_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
-                              struct talloc_dict **members)
+                              struct db_context **members)
 {
        struct wb_group_members_state *state = tevent_req_data(
                req, struct wb_group_members_state);
        NTSTATUS status;
 
+       D_INFO("WB command group_members end.\n");
        if (tevent_req_is_nterror(req, &status)) {
+               D_WARNING("Failed with %s.\n", nt_errstr(status));
                return status;
        }
        *members = talloc_move(mem_ctx, &state->users);