363 lines
9.9 KiB
Diff
363 lines
9.9 KiB
Diff
From 5e04b985acc4c774e0057056887a9f1ed05faf9b Mon Sep 17 00:00:00 2001
|
|
From: Stefan Metzmacher <metze@samba.org>
|
|
Date: Fri, 11 Sep 2020 12:31:13 +0200
|
|
Subject: [PATCH 012/266] CVE-2020-25717 wb_xids2sids: make use of the new
|
|
wb_parent_idmap_setup_send/recv() helpers
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539
|
|
|
|
Signed-off-by: Stefan Metzmacher <metze@samba.org>
|
|
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
|
|
|
|
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556
|
|
|
|
(cherry picked from commit a8f57c94fc2294c309ecb18ea79d0acac86c495b)
|
|
---
|
|
source3/winbindd/wb_xids2sids.c | 255 +++-----------------------------
|
|
1 file changed, 17 insertions(+), 238 deletions(-)
|
|
|
|
Conflict:NA
|
|
Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=5e04b985acc4c774e0057056887a9f1ed05faf9b
|
|
|
|
diff --git a/source3/winbindd/wb_xids2sids.c b/source3/winbindd/wb_xids2sids.c
|
|
index f88c9be58a8..c68939b2bcd 100644
|
|
--- a/source3/winbindd/wb_xids2sids.c
|
|
+++ b/source3/winbindd/wb_xids2sids.c
|
|
@@ -25,231 +25,13 @@
|
|
#include "librpc/gen_ndr/ndr_netlogon.h"
|
|
#include "passdb/lookup_sid.h"
|
|
|
|
-struct wb_xids2sids_dom_map {
|
|
- unsigned low_id;
|
|
- unsigned high_id;
|
|
- const char *name;
|
|
- struct dom_sid sid;
|
|
-};
|
|
-
|
|
-/*
|
|
- * Map idmap ranges to domain names, taken from smb.conf. This is
|
|
- * stored in the parent winbind and used to assemble xid2sid calls
|
|
- * into per-idmap-domain chunks.
|
|
- */
|
|
-static struct wb_xids2sids_dom_map *dom_maps;
|
|
-
|
|
-static bool wb_xids2sids_add_dom(const char *domname,
|
|
- void *private_data)
|
|
-{
|
|
- struct wb_xids2sids_dom_map *map = NULL;
|
|
- size_t num_maps = talloc_array_length(dom_maps);
|
|
- size_t i;
|
|
- const char *range;
|
|
- unsigned low_id, high_id;
|
|
- int ret;
|
|
-
|
|
- range = idmap_config_const_string(domname, "range", NULL);
|
|
- if (range == NULL) {
|
|
- DBG_DEBUG("No range for domain %s found\n", domname);
|
|
- return false;
|
|
- }
|
|
-
|
|
- ret = sscanf(range, "%u - %u", &low_id, &high_id);
|
|
- if (ret != 2) {
|
|
- DBG_DEBUG("Invalid range spec \"%s\" for domain %s\n",
|
|
- range, domname);
|
|
- return false;
|
|
- }
|
|
-
|
|
- if (low_id > high_id) {
|
|
- DBG_DEBUG("Invalid range %u - %u for domain %s\n",
|
|
- low_id, high_id, domname);
|
|
- return false;
|
|
- }
|
|
-
|
|
- for (i=0; i<num_maps; i++) {
|
|
- if (strequal(domname, dom_maps[i].name)) {
|
|
- map = &dom_maps[i];
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- if (map == NULL) {
|
|
- struct wb_xids2sids_dom_map *tmp;
|
|
- char *name;
|
|
-
|
|
- name = talloc_strdup(talloc_tos(), domname);
|
|
- if (name == NULL) {
|
|
- DBG_DEBUG("talloc failed\n");
|
|
- return false;
|
|
- }
|
|
-
|
|
- tmp = talloc_realloc(
|
|
- NULL, dom_maps, struct wb_xids2sids_dom_map,
|
|
- num_maps+1);
|
|
- if (tmp == NULL) {
|
|
- TALLOC_FREE(name);
|
|
- return false;
|
|
- }
|
|
- dom_maps = tmp;
|
|
-
|
|
- map = &dom_maps[num_maps];
|
|
- ZERO_STRUCTP(map);
|
|
- map->name = talloc_move(dom_maps, &name);
|
|
- }
|
|
-
|
|
- map->low_id = low_id;
|
|
- map->high_id = high_id;
|
|
-
|
|
- return false;
|
|
-}
|
|
-
|
|
-struct wb_xids2sids_init_dom_maps_state {
|
|
- struct tevent_context *ev;
|
|
- struct tevent_req *req;
|
|
- size_t dom_idx;
|
|
-};
|
|
-
|
|
-static void wb_xids2sids_init_dom_maps_lookupname_next(
|
|
- struct wb_xids2sids_init_dom_maps_state *state);
|
|
-
|
|
-static void wb_xids2sids_init_dom_maps_lookupname_done(
|
|
- struct tevent_req *subreq);
|
|
-
|
|
-static struct tevent_req *wb_xids2sids_init_dom_maps_send(
|
|
- TALLOC_CTX *mem_ctx, struct tevent_context *ev)
|
|
-{
|
|
- struct tevent_req *req = NULL;
|
|
- struct wb_xids2sids_init_dom_maps_state *state = NULL;
|
|
-
|
|
- req = tevent_req_create(mem_ctx, &state,
|
|
- struct wb_xids2sids_init_dom_maps_state);
|
|
- if (req == NULL) {
|
|
- return NULL;
|
|
- }
|
|
- *state = (struct wb_xids2sids_init_dom_maps_state) {
|
|
- .ev = ev,
|
|
- .req = req,
|
|
- .dom_idx = 0,
|
|
- };
|
|
-
|
|
- if (dom_maps != NULL) {
|
|
- tevent_req_done(req);
|
|
- return tevent_req_post(req, ev);
|
|
- }
|
|
- /*
|
|
- * Put the passdb idmap domain first. We always need to try
|
|
- * there first.
|
|
- */
|
|
-
|
|
- dom_maps = talloc_zero_array(NULL, struct wb_xids2sids_dom_map, 1);
|
|
- if (tevent_req_nomem(dom_maps, req)) {
|
|
- return tevent_req_post(req, ev);
|
|
- }
|
|
- dom_maps[0].low_id = 0;
|
|
- dom_maps[0].high_id = UINT_MAX;
|
|
- dom_maps[0].name = talloc_strdup(dom_maps, get_global_sam_name());
|
|
- if (tevent_req_nomem(dom_maps[0].name, req)) {
|
|
- TALLOC_FREE(dom_maps);
|
|
- return tevent_req_post(req, ev);
|
|
- }
|
|
-
|
|
- lp_scan_idmap_domains(wb_xids2sids_add_dom, NULL);
|
|
-
|
|
- wb_xids2sids_init_dom_maps_lookupname_next(state);
|
|
- if (!tevent_req_is_in_progress(req)) {
|
|
- tevent_req_post(req, ev);
|
|
- }
|
|
- return req;
|
|
-}
|
|
-
|
|
-static void wb_xids2sids_init_dom_maps_lookupname_next(
|
|
- struct wb_xids2sids_init_dom_maps_state *state)
|
|
-{
|
|
- struct tevent_req *subreq = NULL;
|
|
-
|
|
- if (state->dom_idx == talloc_array_length(dom_maps)) {
|
|
- tevent_req_done(state->req);
|
|
- return;
|
|
- }
|
|
-
|
|
- if (strequal(dom_maps[state->dom_idx].name, "*")) {
|
|
- state->dom_idx++;
|
|
- if (state->dom_idx == talloc_array_length(dom_maps)) {
|
|
- tevent_req_done(state->req);
|
|
- return;
|
|
- }
|
|
- }
|
|
-
|
|
- subreq = wb_lookupname_send(state,
|
|
- state->ev,
|
|
- dom_maps[state->dom_idx].name,
|
|
- dom_maps[state->dom_idx].name,
|
|
- "",
|
|
- LOOKUP_NAME_NO_NSS);
|
|
- if (tevent_req_nomem(subreq, state->req)) {
|
|
- return;
|
|
- }
|
|
- tevent_req_set_callback(subreq,
|
|
- wb_xids2sids_init_dom_maps_lookupname_done,
|
|
- state->req);
|
|
-}
|
|
-
|
|
-static void wb_xids2sids_init_dom_maps_lookupname_done(
|
|
- struct tevent_req *subreq)
|
|
-{
|
|
- struct tevent_req *req = tevent_req_callback_data(
|
|
- subreq, struct tevent_req);
|
|
- struct wb_xids2sids_init_dom_maps_state *state = tevent_req_data(
|
|
- req, struct wb_xids2sids_init_dom_maps_state);
|
|
- enum lsa_SidType type;
|
|
- NTSTATUS status;
|
|
-
|
|
- status = wb_lookupname_recv(subreq,
|
|
- &dom_maps[state->dom_idx].sid,
|
|
- &type);
|
|
- TALLOC_FREE(subreq);
|
|
- if (!NT_STATUS_IS_OK(status)) {
|
|
- DBG_WARNING("Lookup domain name '%s' failed '%s'\n",
|
|
- dom_maps[state->dom_idx].name,
|
|
- nt_errstr(status));
|
|
-
|
|
- state->dom_idx++;
|
|
- wb_xids2sids_init_dom_maps_lookupname_next(state);
|
|
- return;
|
|
- }
|
|
-
|
|
- if (type != SID_NAME_DOMAIN) {
|
|
- struct dom_sid_buf buf;
|
|
-
|
|
- DBG_WARNING("SID %s for idmap domain name '%s' "
|
|
- "not a domain SID\n",
|
|
- dom_sid_str_buf(&dom_maps[state->dom_idx].sid,
|
|
- &buf),
|
|
- dom_maps[state->dom_idx].name);
|
|
-
|
|
- ZERO_STRUCT(dom_maps[state->dom_idx].sid);
|
|
- }
|
|
-
|
|
- state->dom_idx++;
|
|
- wb_xids2sids_init_dom_maps_lookupname_next(state);
|
|
-
|
|
- return;
|
|
-}
|
|
-
|
|
-static NTSTATUS wb_xids2sids_init_dom_maps_recv(struct tevent_req *req)
|
|
-{
|
|
- return tevent_req_simple_recv_ntstatus(req);
|
|
-}
|
|
-
|
|
struct wb_xids2sids_dom_state {
|
|
struct tevent_context *ev;
|
|
struct unixid *all_xids;
|
|
const bool *cached;
|
|
size_t num_all_xids;
|
|
struct dom_sid *all_sids;
|
|
- struct wb_xids2sids_dom_map *dom_map;
|
|
+ const struct wb_parent_idmap_config_dom *dom_map;
|
|
bool tried_dclookup;
|
|
|
|
size_t num_dom_xids;
|
|
@@ -262,7 +44,7 @@ static void wb_xids2sids_dom_gotdc(struct tevent_req *subreq);
|
|
|
|
static struct tevent_req *wb_xids2sids_dom_send(
|
|
TALLOC_CTX *mem_ctx, struct tevent_context *ev,
|
|
- struct wb_xids2sids_dom_map *dom_map,
|
|
+ const struct wb_parent_idmap_config_dom *dom_map,
|
|
struct unixid *xids,
|
|
const bool *cached,
|
|
size_t num_xids,
|
|
@@ -334,7 +116,7 @@ static void wb_xids2sids_dom_done(struct tevent_req *subreq)
|
|
subreq, struct tevent_req);
|
|
struct wb_xids2sids_dom_state *state = tevent_req_data(
|
|
req, struct wb_xids2sids_dom_state);
|
|
- struct wb_xids2sids_dom_map *dom_map = state->dom_map;
|
|
+ const struct wb_parent_idmap_config_dom *dom_map = state->dom_map;
|
|
NTSTATUS status, result;
|
|
size_t i;
|
|
size_t dom_sid_idx;
|
|
@@ -437,10 +219,11 @@ struct wb_xids2sids_state {
|
|
bool *cached;
|
|
|
|
size_t dom_idx;
|
|
+ const struct wb_parent_idmap_config *cfg;
|
|
};
|
|
|
|
+static void wb_xids2sids_idmap_setup_done(struct tevent_req *subreq);
|
|
static void wb_xids2sids_done(struct tevent_req *subreq);
|
|
-static void wb_xids2sids_init_dom_maps_done(struct tevent_req *subreq);
|
|
|
|
struct tevent_req *wb_xids2sids_send(TALLOC_CTX *mem_ctx,
|
|
struct tevent_context *ev,
|
|
@@ -495,38 +278,32 @@ struct tevent_req *wb_xids2sids_send(TALLOC_CTX *mem_ctx,
|
|
}
|
|
}
|
|
|
|
- subreq = wb_xids2sids_init_dom_maps_send(
|
|
- state, state->ev);
|
|
+ subreq = wb_parent_idmap_setup_send(state, state->ev);
|
|
if (tevent_req_nomem(subreq, req)) {
|
|
return tevent_req_post(req, ev);
|
|
}
|
|
- tevent_req_set_callback(subreq, wb_xids2sids_init_dom_maps_done, req);
|
|
+ tevent_req_set_callback(subreq, wb_xids2sids_idmap_setup_done, req);
|
|
return req;
|
|
}
|
|
|
|
-static void wb_xids2sids_init_dom_maps_done(struct tevent_req *subreq)
|
|
+static void wb_xids2sids_idmap_setup_done(struct tevent_req *subreq)
|
|
{
|
|
struct tevent_req *req = tevent_req_callback_data(
|
|
subreq, struct tevent_req);
|
|
struct wb_xids2sids_state *state = tevent_req_data(
|
|
req, struct wb_xids2sids_state);
|
|
- size_t num_domains;
|
|
NTSTATUS status;
|
|
|
|
- status = wb_xids2sids_init_dom_maps_recv(subreq);
|
|
+ status = wb_parent_idmap_setup_recv(subreq, &state->cfg);
|
|
TALLOC_FREE(subreq);
|
|
if (tevent_req_nterror(req, status)) {
|
|
return;
|
|
}
|
|
-
|
|
- num_domains = talloc_array_length(dom_maps);
|
|
- if (num_domains == 0) {
|
|
- tevent_req_done(req);
|
|
- return;
|
|
- }
|
|
+ SMB_ASSERT(state->cfg->num_doms > 0);
|
|
|
|
subreq = wb_xids2sids_dom_send(
|
|
- state, state->ev, &dom_maps[state->dom_idx],
|
|
+ state, state->ev,
|
|
+ &state->cfg->doms[state->dom_idx],
|
|
state->xids, state->cached, state->num_xids, state->sids);
|
|
if (tevent_req_nomem(subreq, req)) {
|
|
return;
|
|
@@ -541,7 +318,6 @@ static void wb_xids2sids_done(struct tevent_req *subreq)
|
|
subreq, struct tevent_req);
|
|
struct wb_xids2sids_state *state = tevent_req_data(
|
|
req, struct wb_xids2sids_state);
|
|
- size_t num_domains = talloc_array_length(dom_maps);
|
|
size_t i;
|
|
NTSTATUS status;
|
|
|
|
@@ -553,10 +329,13 @@ static void wb_xids2sids_done(struct tevent_req *subreq)
|
|
|
|
state->dom_idx += 1;
|
|
|
|
- if (state->dom_idx < num_domains) {
|
|
+ if (state->dom_idx < state->cfg->num_doms) {
|
|
+ const struct wb_parent_idmap_config_dom *dom_map =
|
|
+ &state->cfg->doms[state->dom_idx];
|
|
+
|
|
subreq = wb_xids2sids_dom_send(state,
|
|
state->ev,
|
|
- &dom_maps[state->dom_idx],
|
|
+ dom_map,
|
|
state->xids,
|
|
state->cached,
|
|
state->num_xids,
|
|
--
|
|
2.23.0
|
|
|