]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
winbindd: use struct winbindd_domain_ref in struct getpwent_state
authorStefan Metzmacher <metze@samba.org>
Fri, 7 Feb 2025 12:57:45 +0000 (13:57 +0100)
committerRalph Boehme <slow@samba.org>
Sat, 8 Feb 2025 15:26:38 +0000 (15:26 +0000)
In the next commits it will be possible that
struct winbindd_domain instances become stale
because trusted domains were reloaded.

That means aync state structure should not use
pointers to 'struct winbindd_domain' as they
can become stale!

Instead they should use 'struct winbindd_domain_ref domain'
in the async state and use winbindd_domain_ref_set/get()
to manage the 'struct winbindd_domain' pointer.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
source3/winbindd/wb_next_pwent.c
source3/winbindd/winbindd.h

index f000c64a17ee1d1efd2c8e58d890991deaded28c..334ee9bec713d5801c0cb7331cee2799794d4c4a 100644 (file)
@@ -38,22 +38,37 @@ static void wb_next_pwent_send_do(struct tevent_req *req,
 {
        struct tevent_req *subreq;
        struct dom_sid_buf buf, buf1;
+       struct winbindd_domain *domain = NULL;
+       bool valid;
+
+       valid = winbindd_domain_ref_get(&state->gstate->domain,
+                                       &domain);
+       if (!valid) {
+               /*
+                * winbindd_domain_ref_get() already generated
+                * a debug message for the stale domain!
+                */
+               tevent_req_nterror(req, NT_STATUS_NO_MORE_ENTRIES);
+               return;
+       }
 
        if (state->gstate->next_user >= state->gstate->rids.num_rids) {
+
                TALLOC_FREE(state->gstate->rids.rids);
                state->gstate->rids.num_rids = 0;
 
-               state->gstate->domain = wb_next_domain(state->gstate->domain);
-               if (state->gstate->domain == NULL) {
+               domain = wb_next_domain(domain);
+               winbindd_domain_ref_set(&state->gstate->domain, domain);
+               if (domain == NULL) {
                        tevent_req_nterror(req, NT_STATUS_NO_MORE_ENTRIES);
                        return;
                }
 
                D_DEBUG("Query user RID list for domain %s.\n",
-                       state->gstate->domain->name);
+                       domain->name);
                subreq = dcerpc_wbint_QueryUserRidList_send(
                        state, state->ev,
-                       dom_child_handle(state->gstate->domain),
+                       dom_child_handle(domain),
                        &state->gstate->rids);
                if (tevent_req_nomem(subreq, req)) {
                        return;
@@ -63,12 +78,12 @@ static void wb_next_pwent_send_do(struct tevent_req *req,
                return;
        }
 
-       sid_compose(&state->next_sid, &state->gstate->domain->sid,
+       sid_compose(&state->next_sid, &domain->sid,
                    state->gstate->rids.rids[state->gstate->next_user]);
 
        D_DEBUG("Get pw for SID %s composed from domain SID %s and RID %"PRIu32".\n",
                dom_sid_str_buf(&state->next_sid, &buf),
-               dom_sid_str_buf(&state->gstate->domain->sid, &buf1),
+               dom_sid_str_buf(&domain->sid, &buf1),
                state->gstate->rids.rids[state->gstate->next_user]);
        subreq = wb_getpwsid_send(state, state->ev, &state->next_sid,
                                  state->pw);
@@ -116,10 +131,24 @@ static void wb_next_pwent_fetch_done(struct tevent_req *subreq)
                                                    &result);
        TALLOC_FREE(subreq);
        if (any_nt_status_not_ok(status, result, &status)) {
+               struct winbindd_domain *domain = NULL;
+               bool valid;
+
+               valid = winbindd_domain_ref_get(&state->gstate->domain,
+                                               &domain);
+               if (!valid) {
+                       /*
+                        * winbindd_domain_ref_get() already generated
+                        * a debug message for the stale domain!
+                        */
+                       tevent_req_nterror(req, NT_STATUS_NO_MORE_ENTRIES);
+                       return;
+               }
+
                /* Ignore errors here, just log it */
                D_DEBUG("query_user_list for domain %s returned %s\n",
-                          state->gstate->domain->name,
-                          nt_errstr(status));
+                       domain->name,
+                       nt_errstr(status));
                state->gstate->rids.num_rids = 0;
        }
 
index 144fd466e6ef542dc691f87898426436afcc1f80..fb6e10b02d1f3b77be5d99a944d653eb1d6cfe00 100644 (file)
@@ -97,7 +97,7 @@ bool _winbindd_domain_ref_get(struct winbindd_domain_ref *ref,
        _winbindd_domain_ref_get(__ref, __domain, __location__, __func__)
 
 struct getpwent_state {
-       struct winbindd_domain *domain;
+       struct winbindd_domain_ref domain;
        uint32_t next_user;
        struct wbint_RidArray rids;
 };