From: Ralph Boehme Date: Fri, 20 Aug 2021 13:04:49 +0000 (+0200) Subject: CVE-2020-25717 winbind: ensure wb_parent_idmap_setup_send() gets called in winbindd_a... X-Git-Tag: samba-4.13.14~237 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4a39d8a1610b635760ac182be894d206eb0a1ee7;p=thirdparty%2Fsamba.git CVE-2020-25717 winbind: ensure wb_parent_idmap_setup_send() gets called in winbindd_allocate_uid_send() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14804 RN: winbindd can crash because idmap child state is not fully initialized Signed-off-by: Ralph Boehme Reviewed-by: Volker Lendecke Autobuild-User(master): Volker Lendecke Autobuild-Date(master): Thu Sep 2 15:20:06 UTC 2021 on sn-devel-184 (cherry picked from commit d0f6d54354b02f5591706814fbd1e4844788fdfa) BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 (cherry picked from commit 446f89510f2e55a551e2975a6cbf01c6a023ba0c) --- diff --git a/source3/winbindd/winbindd_allocate_uid.c b/source3/winbindd/winbindd_allocate_uid.c index 69ce61c872e..64711f1b661 100644 --- a/source3/winbindd/winbindd_allocate_uid.c +++ b/source3/winbindd/winbindd_allocate_uid.c @@ -22,9 +22,11 @@ #include "librpc/gen_ndr/ndr_winbind_c.h" struct winbindd_allocate_uid_state { + struct tevent_context *ev; uint64_t uid; }; +static void winbindd_allocate_uid_initialized(struct tevent_req *subreq); static void winbindd_allocate_uid_done(struct tevent_req *subreq); struct tevent_req *winbindd_allocate_uid_send(TALLOC_CTX *mem_ctx, @@ -34,25 +36,57 @@ struct tevent_req *winbindd_allocate_uid_send(TALLOC_CTX *mem_ctx, { struct tevent_req *req, *subreq; struct winbindd_allocate_uid_state *state; - struct dcerpc_binding_handle *child_binding_handle = NULL; req = tevent_req_create(mem_ctx, &state, struct winbindd_allocate_uid_state); if (req == NULL) { return NULL; } + state->ev = ev; DEBUG(3, ("allocate_uid\n")); - child_binding_handle = idmap_child_handle(); + subreq = wb_parent_idmap_setup_send(state, ev); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, winbindd_allocate_uid_initialized, req); + return req; +} + +static void winbindd_allocate_uid_initialized(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct dcerpc_binding_handle *child_binding_handle = NULL; + struct winbindd_allocate_uid_state *state = tevent_req_data( + req, struct winbindd_allocate_uid_state); + const struct wb_parent_idmap_config *cfg = NULL; + NTSTATUS status; + + status = wb_parent_idmap_setup_recv(subreq, &cfg); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + if (cfg->num_doms == 0) { + /* + * idmap_tdb also returns UNSUCCESSFUL if a range is full + */ + tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL); + return; + } + + child_binding_handle = idmap_child_handle(); - subreq = dcerpc_wbint_AllocateUid_send(state, ev, child_binding_handle, + subreq = dcerpc_wbint_AllocateUid_send(state, + state->ev, + child_binding_handle, &state->uid); if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); + return; } tevent_req_set_callback(subreq, winbindd_allocate_uid_done, req); - return req; } static void winbindd_allocate_uid_done(struct tevent_req *subreq)