From 8396571ce335758e4814220a2959fc3d4efec60d Mon Sep 17 00:00:00 2001 From: kircher Date: Thu, 25 Nov 2021 22:08:49 +0800 Subject: [PATCH] CVE-2020-25717 --- ...inbindd-add-generic-wb_parent_idmap_.patch | 411 ++++++++++++++++++ ...b_xids2sids-make-use-of-the-new-wb_p.patch | 362 +++++++++++++++ ...b_sids2xids-call-wb_parent_idmap_set.patch | 94 ++++ ...inbindd-defer-the-setup_child-from-i.patch | 96 ++++ ...b_sids2xids-build-state-idmap_doms-b.patch | 169 +++++++ ...inbindd-allow-idmap-backends-to-mark.patch | 83 ++++ ...3-idmap_hash-reliable-return-ID_TYPE.patch | 104 +++++ ...inbindd-call-wb_parent_idmap_setup_s.patch | 81 ++++ ...inbind-ensure-wb_parent_idmap_setup_.patch | 109 +++++ ...uth_sam-use-pdb_get_domain_info-to-l.patch | 228 ++++++++++ ...3-winbindd-make-sure-we-default-to-r.patch | 176 ++++++++ ...4-auth-ntlm-make-sure-auth_check_pas.patch | 39 ++ ...oadparm-Add-new-parameter-min-domain.patch | 101 +++++ ...717-s3-auth-Check-minimum-domain-uid.patch | 53 +++ ...3-auth-we-should-not-try-to-autocrea.patch | 36 ++ ...3-auth-no-longer-let-check_account-a.patch | 42 ++ ...3-auth-remove-fallbacks-in-smb_getpw.patch | 181 ++++++++ ...3-auth-don-t-let-create_local_token-.patch | 48 ++ ...VE-2020-25717-auth-gensec-always-req.patch | 76 ++++ ...3-ntlm_auth-fix-memory-leaks-in-ntlm.patch | 77 ++++ ...3-ntlm_auth-let-ntlm_auth_generate_s.patch | 145 ++++++ ...nfo-in-auth3_generate_session_info_p.patch | 52 +++ ...3-auth-let-auth3_generate_session_in.patch | 319 ++++++++++++++ ...3-auth-let-auth3_generate_session_in.patch | 85 ++++ ...1456624-Uninitialized-scalar-variabl.patch | 33 ++ samba.spec | 35 +- 26 files changed, 3234 insertions(+), 1 deletion(-) create mode 100644 backport-0001-CVE-2020-25717-winbindd-add-generic-wb_parent_idmap_.patch create mode 100644 backport-0002-CVE-2020-25717-wb_xids2sids-make-use-of-the-new-wb_p.patch create mode 100644 backport-0003-CVE-2020-25717-wb_sids2xids-call-wb_parent_idmap_set.patch create mode 100644 backport-0004-CVE-2020-25717-winbindd-defer-the-setup_child-from-i.patch create mode 100644 backport-0005-CVE-2020-25717-wb_sids2xids-build-state-idmap_doms-b.patch create mode 100644 backport-0006-CVE-2020-25717-winbindd-allow-idmap-backends-to-mark.patch create mode 100644 backport-0007-CVE-2020-25717-s3-idmap_hash-reliable-return-ID_TYPE.patch create mode 100644 backport-0008-CVE-2020-25717-winbindd-call-wb_parent_idmap_setup_s.patch create mode 100644 backport-0009-CVE-2020-25717-winbind-ensure-wb_parent_idmap_setup_.patch create mode 100644 backport-0010-CVE-2020-25717-auth_sam-use-pdb_get_domain_info-to-l.patch create mode 100644 backport-0011-CVE-2020-25717-s3-winbindd-make-sure-we-default-to-r.patch create mode 100644 backport-0012-CVE-2020-25717-s4-auth-ntlm-make-sure-auth_check_pas.patch create mode 100644 backport-0013-CVE-2020-25717-loadparm-Add-new-parameter-min-domain.patch create mode 100644 backport-0014-CVE-2020-25717-s3-auth-Check-minimum-domain-uid.patch create mode 100644 backport-0015-CVE-2020-25717-s3-auth-we-should-not-try-to-autocrea.patch create mode 100644 backport-0016-CVE-2020-25717-s3-auth-no-longer-let-check_account-a.patch create mode 100644 backport-0017-CVE-2020-25717-s3-auth-remove-fallbacks-in-smb_getpw.patch create mode 100644 backport-0018-CVE-2020-25717-s3-auth-don-t-let-create_local_token-.patch create mode 100644 backport-0019-CVE-2020-25719-CVE-2020-25717-auth-gensec-always-req.patch create mode 100644 backport-0020-CVE-2020-25717-s3-ntlm_auth-fix-memory-leaks-in-ntlm.patch create mode 100644 backport-0021-CVE-2020-25717-s3-ntlm_auth-let-ntlm_auth_generate_s.patch create mode 100644 backport-0022-use-set_current_user_info-in-auth3_generate_session_info_p.patch create mode 100644 backport-0023-CVE-2020-25717-s3-auth-let-auth3_generate_session_in.patch create mode 100644 backport-0024-CVE-2020-25717-s3-auth-let-auth3_generate_session_in.patch create mode 100644 backport-winbind-Fix-CID-1456624-Uninitialized-scalar-variabl.patch diff --git a/backport-0001-CVE-2020-25717-winbindd-add-generic-wb_parent_idmap_.patch b/backport-0001-CVE-2020-25717-winbindd-add-generic-wb_parent_idmap_.patch new file mode 100644 index 0000000..ac5b545 --- /dev/null +++ b/backport-0001-CVE-2020-25717-winbindd-add-generic-wb_parent_idmap_.patch @@ -0,0 +1,411 @@ +From f3957ca5ce206e1224874e6495780b5130d6de0c Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 11 Sep 2020 12:16:00 +0200 +Subject: [PATCH 011/266] CVE-2020-25717 winbindd: add generic + wb_parent_idmap_setup_send/recv() helpers + +This is more or less a copy of wb_xids2sids_init_dom_maps_send/recv, +but it's more generic and doesn't imply global state. + +It also closes a initialization race by using a tevent_queue to +serialize the calls. + +In the next commits we'll replace wb_xids2sids_init_dom_maps_send/recv. + +We'll also use the new function in the wb_sids2xids code. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Gary Lockyer + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +(cherry picked from commit 209e81a2ea8c972ee57e2f0c9579da843c0e2ac7) +--- + source3/winbindd/winbindd.h | 13 ++ + source3/winbindd/winbindd_idmap.c | 314 ++++++++++++++++++++++++++++++ + source3/winbindd/winbindd_proto.h | 5 + + 3 files changed, 332 insertions(+) + +Conflict:bool is_idmap_child(const struct winbindd_child *child); --> struct dcerpc_binding_handle *idmap_child_handle(void); +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=f3957ca5ce206e1224874e6495780b5130d6de0c + +diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h +index a72d6aa7830..480ba4f1282 100644 +--- a/source3/winbindd/winbindd.h ++++ b/source3/winbindd/winbindd.h +@@ -189,6 +189,19 @@ struct winbindd_domain { + struct winbindd_domain *prev, *next; + }; + ++struct wb_parent_idmap_config_dom { ++ unsigned low_id; ++ unsigned high_id; ++ const char *name; ++ struct dom_sid sid; ++}; ++ ++struct wb_parent_idmap_config { ++ struct tevent_queue *queue; ++ uint32_t num_doms; ++ struct wb_parent_idmap_config_dom *doms; ++}; ++ + struct wb_acct_info { + const char *acct_name; /* account name */ + const char *acct_desc; /* account name */ +diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c +index bd5f3a67aad..487f27fd94d 100644 +--- a/source3/winbindd/winbindd_idmap.c ++++ b/source3/winbindd/winbindd_idmap.c +@@ -23,12 +23,21 @@ + + #include "includes.h" + #include "winbindd.h" ++#include "../libcli/security/security.h" ++#include "passdb/lookup_sid.h" + + #undef DBGC_CLASS + #define DBGC_CLASS DBGC_WINBIND + + static struct winbindd_child static_idmap_child; + ++/* ++ * Map idmap ranges to domain names, taken from smb.conf. This is ++ * stored in the parent winbind and used to assemble xids2sids/sids2xids calls ++ * into per-idmap-domain chunks. ++ */ ++static struct wb_parent_idmap_config static_parent_idmap_config; ++ + struct winbindd_child *idmap_child(void) + { + return &static_idmap_child; +@@ -73,3 +82,308 @@ void init_idmap_child(void) + idmap_dispatch_table, + "log.winbindd", "idmap"); + } ++ ++struct wb_parent_idmap_setup_state { ++ struct tevent_context *ev; ++ struct wb_parent_idmap_config *cfg; ++ size_t dom_idx; ++}; ++ ++static void wb_parent_idmap_setup_cleanup(struct tevent_req *req, ++ enum tevent_req_state req_state) ++{ ++ struct wb_parent_idmap_setup_state *state = ++ tevent_req_data(req, ++ struct wb_parent_idmap_setup_state); ++ ++ if (req_state == TEVENT_REQ_DONE) { ++ state->cfg = NULL; ++ return; ++ } ++ ++ if (state->cfg == NULL) { ++ return; ++ } ++ ++ state->cfg->num_doms = 0; ++ TALLOC_FREE(state->cfg->doms); ++ state->cfg = NULL; ++} ++ ++static void wb_parent_idmap_setup_queue_wait_done(struct tevent_req *subreq); ++static bool wb_parent_idmap_setup_scan_config(const char *domname, ++ void *private_data); ++static void wb_parent_idmap_setup_lookupname_next(struct tevent_req *req); ++static void wb_parent_idmap_setup_lookupname_done(struct tevent_req *subreq); ++ ++struct tevent_req *wb_parent_idmap_setup_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev) ++{ ++ struct tevent_req *req = NULL; ++ struct wb_parent_idmap_setup_state *state = NULL; ++ struct tevent_req *subreq = NULL; ++ ++ req = tevent_req_create(mem_ctx, &state, ++ struct wb_parent_idmap_setup_state); ++ if (req == NULL) { ++ return NULL; ++ } ++ *state = (struct wb_parent_idmap_setup_state) { ++ .ev = ev, ++ .cfg = &static_parent_idmap_config, ++ .dom_idx = 0, ++ }; ++ ++ if (state->cfg->queue == NULL) { ++ state->cfg->queue = tevent_queue_create(NULL, ++ "wb_parent_idmap_config_queue"); ++ if (tevent_req_nomem(state->cfg->queue, req)) { ++ return tevent_req_post(req, ev); ++ } ++ } ++ ++ subreq = tevent_queue_wait_send(state, state->ev, state->cfg->queue); ++ if (tevent_req_nomem(subreq, req)) { ++ return tevent_req_post(req, ev); ++ } ++ tevent_req_set_callback(subreq, ++ wb_parent_idmap_setup_queue_wait_done, ++ req); ++ ++ return req; ++} ++ ++static void wb_parent_idmap_setup_queue_wait_done(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = ++ tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct wb_parent_idmap_setup_state *state = ++ tevent_req_data(req, ++ struct wb_parent_idmap_setup_state); ++ bool ok; ++ ++ /* ++ * Note we don't call TALLOC_FREE(subreq) here in order to block the ++ * queue until tevent_req_received() in wb_parent_idmap_setup_recv() ++ * will destroy it implicitly. ++ */ ++ ok = tevent_queue_wait_recv(subreq); ++ if (!ok) { ++ DBG_ERR("tevent_queue_wait_recv() failed\n"); ++ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); ++ return; ++ } ++ ++ if (state->cfg->num_doms != 0) { ++ /* ++ * If we're not the first one we're done. ++ */ ++ tevent_req_done(req); ++ return; ++ } ++ ++ /* ++ * From this point we start changing state->cfg, ++ * which is &static_parent_idmap_config, ++ * so we better setup a cleanup function ++ * to undo the changes on failure. ++ */ ++ tevent_req_set_cleanup_fn(req, wb_parent_idmap_setup_cleanup); ++ ++ /* ++ * Put the passdb idmap domain first. We always need to try ++ * there first. ++ */ ++ state->cfg->doms = talloc_zero_array(NULL, ++ struct wb_parent_idmap_config_dom, ++ 1); ++ if (tevent_req_nomem(state->cfg->doms, req)) { ++ return; ++ } ++ state->cfg->doms[0].low_id = 0; ++ state->cfg->doms[0].high_id = UINT_MAX; ++ state->cfg->doms[0].name = talloc_strdup(state->cfg->doms, ++ get_global_sam_name()); ++ if (tevent_req_nomem(state->cfg->doms[0].name, req)) { ++ return; ++ } ++ state->cfg->num_doms += 1; ++ ++ lp_scan_idmap_domains(wb_parent_idmap_setup_scan_config, req); ++ if (!tevent_req_is_in_progress(req)) { ++ return; ++ } ++ ++ wb_parent_idmap_setup_lookupname_next(req); ++} ++ ++static bool wb_parent_idmap_setup_scan_config(const char *domname, ++ void *private_data) ++{ ++ struct tevent_req *req = ++ talloc_get_type_abort(private_data, ++ struct tevent_req); ++ struct wb_parent_idmap_setup_state *state = ++ tevent_req_data(req, ++ struct wb_parent_idmap_setup_state); ++ struct wb_parent_idmap_config_dom *map = NULL; ++ 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; icfg->num_doms; i++) { ++ if (strequal(domname, state->cfg->doms[i].name)) { ++ map = &state->cfg->doms[i]; ++ break; ++ } ++ } ++ ++ if (map == NULL) { ++ struct wb_parent_idmap_config_dom *tmp; ++ char *name; ++ ++ name = talloc_strdup(state, domname); ++ if (name == NULL) { ++ DBG_ERR("talloc failed\n"); ++ return false; ++ } ++ ++ tmp = talloc_realloc( ++ NULL, state->cfg->doms, struct wb_parent_idmap_config_dom, ++ state->cfg->num_doms+1); ++ if (tmp == NULL) { ++ DBG_ERR("talloc failed\n"); ++ return false; ++ } ++ state->cfg->doms = tmp; ++ ++ map = &state->cfg->doms[state->cfg->num_doms]; ++ state->cfg->num_doms += 1; ++ ZERO_STRUCTP(map); ++ map->name = talloc_move(state->cfg->doms, &name); ++ } ++ ++ map->low_id = low_id; ++ map->high_id = high_id; ++ ++ return false; ++} ++ ++static void wb_parent_idmap_setup_lookupname_next(struct tevent_req *req) ++{ ++ struct wb_parent_idmap_setup_state *state = ++ tevent_req_data(req, ++ struct wb_parent_idmap_setup_state); ++ struct wb_parent_idmap_config_dom *dom = ++ &state->cfg->doms[state->dom_idx]; ++ struct tevent_req *subreq = NULL; ++ ++ next_domain: ++ if (state->dom_idx == state->cfg->num_doms) { ++ tevent_req_done(req); ++ return; ++ } ++ ++ if (strequal(dom->name, "*")) { ++ state->dom_idx++; ++ goto next_domain; ++ } ++ ++ subreq = wb_lookupname_send(state, ++ state->ev, ++ dom->name, ++ dom->name, ++ "", ++ LOOKUP_NAME_NO_NSS); ++ if (tevent_req_nomem(subreq, req)) { ++ return; ++ } ++ tevent_req_set_callback(subreq, ++ wb_parent_idmap_setup_lookupname_done, ++ req); ++} ++ ++static void wb_parent_idmap_setup_lookupname_done(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = ++ tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct wb_parent_idmap_setup_state *state = ++ tevent_req_data(req, ++ struct wb_parent_idmap_setup_state); ++ struct wb_parent_idmap_config_dom *dom = ++ &state->cfg->doms[state->dom_idx]; ++ enum lsa_SidType type; ++ NTSTATUS status; ++ ++ status = wb_lookupname_recv(subreq, &dom->sid, &type); ++ TALLOC_FREE(subreq); ++ if (!NT_STATUS_IS_OK(status)) { ++ DBG_ERR("Lookup domain name '%s' failed '%s'\n", ++ dom->name, ++ nt_errstr(status)); ++ ++ state->dom_idx++; ++ wb_parent_idmap_setup_lookupname_next(req); ++ return; ++ } ++ ++ if (type != SID_NAME_DOMAIN) { ++ struct dom_sid_buf buf; ++ ++ DBG_ERR("SID %s for idmap domain name '%s' " ++ "not a domain SID\n", ++ dom_sid_str_buf(&dom->sid, &buf), ++ dom->name); ++ ++ ZERO_STRUCT(dom->sid); ++ } ++ ++ state->dom_idx++; ++ wb_parent_idmap_setup_lookupname_next(req); ++ ++ return; ++} ++ ++NTSTATUS wb_parent_idmap_setup_recv(struct tevent_req *req, ++ const struct wb_parent_idmap_config **_cfg) ++{ ++ const struct wb_parent_idmap_config *cfg = &static_parent_idmap_config; ++ NTSTATUS status; ++ ++ *_cfg = NULL; ++ ++ if (tevent_req_is_nterror(req, &status)) { ++ tevent_req_received(req); ++ return status; ++ } ++ ++ /* ++ * Note state->cfg is already set to NULL by ++ * wb_parent_idmap_setup_cleanup() ++ */ ++ *_cfg = cfg; ++ tevent_req_received(req); ++ return NT_STATUS_OK; ++} +diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h +index 97c38018aac..8923bb3124f 100644 +--- a/source3/winbindd/winbindd_proto.h ++++ b/source3/winbindd/winbindd_proto.h +@@ -364,6 +364,11 @@ NTSTATUS winbindd_print_groupmembers(struct db_context *members, + + /* The following definitions come from winbindd/winbindd_idmap.c */ + ++struct tevent_req *wb_parent_idmap_setup_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev); ++NTSTATUS wb_parent_idmap_setup_recv(struct tevent_req *req, ++ const struct wb_parent_idmap_config **_cfg); ++ + void init_idmap_child(void); + struct winbindd_child *idmap_child(void); + struct dcerpc_binding_handle *idmap_child_handle(void); +-- +2.23.0 + diff --git a/backport-0002-CVE-2020-25717-wb_xids2sids-make-use-of-the-new-wb_p.patch b/backport-0002-CVE-2020-25717-wb_xids2sids-make-use-of-the-new-wb_p.patch new file mode 100644 index 0000000..259f795 --- /dev/null +++ b/backport-0002-CVE-2020-25717-wb_xids2sids-make-use-of-the-new-wb_p.patch @@ -0,0 +1,362 @@ +From 5e04b985acc4c774e0057056887a9f1ed05faf9b Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +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 +Reviewed-by: Gary Lockyer + +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; iname = 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 + diff --git a/backport-0003-CVE-2020-25717-wb_sids2xids-call-wb_parent_idmap_set.patch b/backport-0003-CVE-2020-25717-wb_sids2xids-call-wb_parent_idmap_set.patch new file mode 100644 index 0000000..c6e3162 --- /dev/null +++ b/backport-0003-CVE-2020-25717-wb_sids2xids-call-wb_parent_idmap_set.patch @@ -0,0 +1,94 @@ +From a3cca16fac5d834f2f29e1daa31ced38938fada9 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 11 Sep 2020 12:52:40 +0200 +Subject: [PATCH 013/266] CVE-2020-25717 wb_sids2xids: call + wb_parent_idmap_setup_send/recv as the first step + +This isn't really used yet, but it will in the next commits. + +Also idmap_child_handle() will soon assert that +wb_parent_idmap_setup_send/recv() was called before it's used. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Gary Lockyer + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +(cherry picked from commit d42aaeba6e0820acd17f204ff7ab6d1aede1b303) + +Conflict:NA +Reference:https://gitlab.com/samba-team/samba/-/commit/a3cca16fac5d834f2f29e1daa31ced38938fada9 +--- + source3/winbindd/wb_sids2xids.c | 34 +++++++++++++++++++++++++++++---- + 1 file changed, 30 insertions(+), 4 deletions(-) + +diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c +index b47856520ea..59f6ba5891e 100644 +--- a/source3/winbindd/wb_sids2xids.c ++++ b/source3/winbindd/wb_sids2xids.c +@@ -29,6 +29,8 @@ + struct wb_sids2xids_state { + struct tevent_context *ev; + ++ const struct wb_parent_idmap_config *cfg; ++ + struct dom_sid *sids; + uint32_t num_sids; + +@@ -58,7 +60,7 @@ struct wb_sids2xids_state { + struct wbint_TransIDArray ids; + }; + +- ++static void wb_sids2xids_idmap_setup_done(struct tevent_req *subreq); + static bool wb_sids2xids_in_cache(struct dom_sid *sid, struct id_map *map); + static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq); + static void wb_sids2xids_done(struct tevent_req *subreq); +@@ -126,15 +128,39 @@ struct tevent_req *wb_sids2xids_send(TALLOC_CTX *mem_ctx, + return tevent_req_post(req, ev); + } + +- subreq = wb_lookupsids_send(state, ev, state->non_cached, +- state->num_non_cached); ++ 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_sids2xids_lookupsids_done, req); ++ tevent_req_set_callback(subreq, wb_sids2xids_idmap_setup_done, req); + return req; + } + ++static void wb_sids2xids_idmap_setup_done(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = tevent_req_callback_data( ++ subreq, struct tevent_req); ++ struct wb_sids2xids_state *state = tevent_req_data( ++ req, struct wb_sids2xids_state); ++ NTSTATUS status; ++ ++ status = wb_parent_idmap_setup_recv(subreq, &state->cfg); ++ TALLOC_FREE(subreq); ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ SMB_ASSERT(state->cfg->num_doms > 0); ++ ++ subreq = wb_lookupsids_send(state, ++ state->ev, ++ state->non_cached, ++ state->num_non_cached); ++ if (tevent_req_nomem(subreq, req)) { ++ return; ++ } ++ tevent_req_set_callback(subreq, wb_sids2xids_lookupsids_done, req); ++} ++ + static bool wb_sids2xids_in_cache(struct dom_sid *sid, struct id_map *map) + { + struct unixid id; +-- +2.23.0 + diff --git a/backport-0004-CVE-2020-25717-winbindd-defer-the-setup_child-from-i.patch b/backport-0004-CVE-2020-25717-winbindd-defer-the-setup_child-from-i.patch new file mode 100644 index 0000000..666482e --- /dev/null +++ b/backport-0004-CVE-2020-25717-winbindd-defer-the-setup_child-from-i.patch @@ -0,0 +1,96 @@ +From 3812930e641d10d1ead10b52ddc7240dd585d0f6 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 11 Sep 2020 15:42:42 +0200 +Subject: [PATCH 016/266] CVE-2020-25717 winbindd: defer the setup_child() from + init_idmap_child() + +At startup we trigger a wb_parent_idmap_setup_send() and make +sure setup_child() is called just before wb_parent_idmap_setup_recv() +finished. + +This makes sure our view of the idmap config in the parent matches +what we have in the child. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Gary Lockyer + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +(cherry picked from commit 28e020c0a863411cfa95e3b1ed943d922b8635bd) +--- + source3/winbindd/winbindd_idmap.c | 45 ++++++++++++++++++++++++++++--- + 1 file changed, 42 insertions(+), 3 deletions(-) + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=3812930e641d10d1ead10b52ddc7240dd585d0f6 + +diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c +index 14836e3b8a0..3e2461478a9 100644 +--- a/source3/winbindd/winbindd_idmap.c ++++ b/source3/winbindd/winbindd_idmap.c +@@ -81,11 +81,44 @@ static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = { + } + }; + ++static void init_idmap_child_done(struct tevent_req *subreq); ++ + void init_idmap_child(void) + { +- setup_child(NULL, &static_idmap_child, +- idmap_dispatch_table, +- "log.winbindd", "idmap"); ++ struct tevent_req *subreq = NULL; ++ ++ subreq = wb_parent_idmap_setup_send(global_event_context(), ++ global_event_context()); ++ if (subreq == NULL) { ++ /* ++ * This is only an optimization, so we're free to ++ * to ignore errors ++ */ ++ DBG_ERR("wb_parent_idmap_setup_send() failed\n"); ++ return; ++ } ++ tevent_req_set_callback(subreq, init_idmap_child_done, NULL); ++ DBG_DEBUG("wb_parent_idmap_setup_send() started\n"); ++} ++ ++static void init_idmap_child_done(struct tevent_req *subreq) ++{ ++ const struct wb_parent_idmap_config *cfg = NULL; ++ NTSTATUS status; ++ ++ status = wb_parent_idmap_setup_recv(subreq, &cfg); ++ TALLOC_FREE(subreq); ++ if (!NT_STATUS_IS_OK(status)) { ++ /* ++ * This is only an optimization, so we're free to ++ * to ignore errors ++ */ ++ DBG_ERR("wb_parent_idmap_setup_recv() failed %s\n", ++ nt_errstr(status)); ++ return; ++ } ++ ++ DBG_DEBUG("wb_parent_idmap_setup_recv() finished\n"); + } + + struct wb_parent_idmap_setup_state { +@@ -306,6 +339,12 @@ static void wb_parent_idmap_setup_lookupname_next(struct tevent_req *req) + + next_domain: + if (state->dom_idx == state->cfg->num_doms) { ++ /* ++ * We're done, so start the idmap child ++ */ ++ setup_child(NULL, &static_idmap_child, ++ idmap_dispatch_table, ++ "log.winbindd", "idmap"); + tevent_req_done(req); + return; + } +-- +2.23.0 + diff --git a/backport-0005-CVE-2020-25717-wb_sids2xids-build-state-idmap_doms-b.patch b/backport-0005-CVE-2020-25717-wb_sids2xids-build-state-idmap_doms-b.patch new file mode 100644 index 0000000..efb5256 --- /dev/null +++ b/backport-0005-CVE-2020-25717-wb_sids2xids-build-state-idmap_doms-b.patch @@ -0,0 +1,169 @@ +From ed1542b9f37734bc77906c4ba49ea6ea3be09af8 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 10 Sep 2020 17:13:14 +0200 +Subject: [PATCH 026/266] CVE-2020-25717 wb_sids2xids: build state->idmap_doms + based on wb_parent_idmap_config + +In future we'll try to avoid wb_lookupsids_send() and only call +it if needed. + +The domain name passed should be only relevant to find the correct +idmap backend, and these should all be available in +wb_parent_idmap_config as it was created before the idmap child was forked. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Gary Lockyer + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +(cherry picked from commit c55f4f37589130a0d8952489da175bbcf53f6748) +--- + source3/winbindd/wb_sids2xids.c | 101 +++++++++++++++++++------------- + 1 file changed, 61 insertions(+), 40 deletions(-) + +Conflict:lookup_sids --> non_cached +lookup_count --> num_non_cached +li --> i +delete 'uint32_t ai = state->tmp_idx[i]' +state->all_ids.ids[i] --> &state->ids.ids[i] +add 't->xid.id = UINT32_MAX; +t->xid.type = t->type;' +type_hint --> type +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=ed1542b9f37734bc77906c4ba49ea6ea3be09af8 + +diff --git a/source3/winbindd/wb_sids2xids.c b/source3/winbindd/wb_sids2xids.c +index 21bf5f901f3..3a3d47abbe5 100644 +--- a/source3/winbindd/wb_sids2xids.c ++++ b/source3/winbindd/wb_sids2xids.c +@@ -193,6 +193,7 @@ static void wb_sids2xids_idmap_setup_done(struct tevent_req *subreq) + struct wb_sids2xids_state *state = tevent_req_data( + req, struct wb_sids2xids_state); + NTSTATUS status; ++ uint32_t i; + + status = wb_parent_idmap_setup_recv(subreq, &state->cfg); + TALLOC_FREE(subreq); +@@ -201,6 +202,66 @@ static void wb_sids2xids_idmap_setup_done(struct tevent_req *subreq) + } + SMB_ASSERT(state->cfg->num_doms > 0); + ++ /* ++ * Now we build a list with all domain ++ * with non cached entries ++ */ ++ for (i=0; inum_sids; i++) { ++ struct wbint_TransID *t = &state->ids.ids[i]; ++ struct dom_sid domain_sid; ++ const char *domain_name = NULL; ++ int domain_index; ++ uint32_t rid = 0; ++ uint32_t di; ++ ++ if (t->domain_index == UINT32_MAX) { ++ /* ignore already filled entries */ ++ continue; ++ } ++ ++ sid_copy(&domain_sid, &state->sids[i]); ++ sid_split_rid(&domain_sid, &rid); ++ ++ for (di = 0; di < state->cfg->num_doms; di++) { ++ struct wb_parent_idmap_config_dom *dom = ++ &state->cfg->doms[di]; ++ bool match; ++ ++ match = dom_sid_equal(&domain_sid, ++ &dom->sid); ++ if (!match) { ++ continue; ++ } ++ ++ domain_name = dom->name; ++ break; ++ } ++ if (domain_name == NULL) { ++ struct winbindd_domain *wb_domain = NULL; ++ ++ /* ++ * Try to fill the name if we already know it ++ */ ++ wb_domain = find_domain_from_sid_noinit(&state->sids[i]); ++ if (wb_domain != NULL) { ++ domain_name = wb_domain->name; ++ } ++ } ++ if (domain_name == NULL) { ++ domain_name = ""; ++ } ++ ++ domain_index = init_lsa_ref_domain_list(state, ++ &state->idmap_doms, ++ domain_name, ++ &domain_sid); ++ if (domain_index == -1) { ++ tevent_req_oom(req); ++ return; ++ } ++ t->domain_index = domain_index; ++ } ++ + subreq = wb_lookupsids_send(state, + state->ev, + state->non_cached, +@@ -251,51 +312,11 @@ static void wb_sids2xids_lookupsids_done(struct tevent_req *subreq) + } + + for (i=0; inum_non_cached; i++) { +- const struct dom_sid *sid = &state->non_cached[i]; +- struct dom_sid dom_sid; + struct lsa_TranslatedName *n = &names->names[i]; + struct wbint_TransID *t = &state->ids.ids[i]; +- int domain_index; +- const char *domain_name = NULL; +- +- if (n->sid_index != UINT32_MAX) { +- const struct lsa_DomainInfo *info; +- bool match; +- +- info = &domains->domains[n->sid_index]; +- match = dom_sid_in_domain(info->sid, sid); +- if (match) { +- domain_name = info->name.string; +- } +- } +- if (domain_name == NULL) { +- struct winbindd_domain *wb_domain = NULL; +- +- /* +- * This is needed to handle Samba DCs +- * which always return sid_index == UINT32_MAX for +- * unknown sids. +- */ +- wb_domain = find_domain_from_sid_noinit(sid); +- if (wb_domain != NULL) { +- domain_name = wb_domain->name; +- } +- } +- if (domain_name == NULL) { +- domain_name = ""; +- } + +- sid_copy(&dom_sid, sid); +- sid_split_rid(&dom_sid, &t->rid); + t->type = lsa_SidType_to_id_type(n->sid_type); +- domain_index = init_lsa_ref_domain_list( +- state, &state->idmap_doms, domain_name, &dom_sid); +- if (domain_index == -1) { +- tevent_req_oom(req); +- return; +- } +- t->domain_index = domain_index; + + t->xid.id = UINT32_MAX; + t->xid.type = t->type; + } +-- +2.23.0 + diff --git a/backport-0006-CVE-2020-25717-winbindd-allow-idmap-backends-to-mark.patch b/backport-0006-CVE-2020-25717-winbindd-allow-idmap-backends-to-mark.patch new file mode 100644 index 0000000..9bd8ff6 --- /dev/null +++ b/backport-0006-CVE-2020-25717-winbindd-allow-idmap-backends-to-mark.patch @@ -0,0 +1,83 @@ +From 04e10a843187810e97bf565731ddc5d70b0f4245 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 15 Sep 2020 17:26:11 +0200 +Subject: [PATCH 027/266] CVE-2020-25717 winbindd: allow idmap backends to mark + entries with ID_[TYPE_WB_]REQUIRE_TYPE + +This must only be used between winbindd parent and child! +It must not leak into outside world. + +Some backends require ID_TYPE_UID or ID_TYPE_GID as type_hint, +while others may only need ID_TYPE_BOTH in order to validate that +the domain exists. + +This will allow us to skip the wb_lookupsids_send/recv in the winbindd parent +in future and only do that on demand. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Gary Lockyer + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +(cherry picked from commit 493f5d6b078e0b0f80d1ef25043e2834cb4fcb87) +--- + librpc/idl/idmap.idl | 23 +++++++++++++++++-- + source3/passdb/lookup_sid.c | 7 ++++++ + source3/winbindd/idmap_autorid.c | 6 ++--- + source3/winbindd/idmap_ldap.c | 29 ++++++++++++++++++++++++ + source3/winbindd/idmap_rw.c | 32 +++++++++++++++++++++++++-- + source3/winbindd/idmap_tdb_common.c | 22 +++++++++++++++++- + source3/winbindd/wb_sids2xids.c | 11 +++++++++ + source3/winbindd/winbindd_dual_srv.c | 6 +++++ + source3/winbindd/winbindd_getgroups.c | 7 ++++++ + 9 files changed, 135 insertions(+), 8 deletions(-) + +Conflict:only remain the first chunk +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=04e10a843187810e97bf565731ddc5d70b0f4245 + +diff --git a/librpc/idl/idmap.idl b/librpc/idl/idmap.idl +index 54fd888dcab..e58e39210c7 100644 +--- a/librpc/idl/idmap.idl ++++ b/librpc/idl/idmap.idl +@@ -11,7 +11,18 @@ interface idmap + ID_TYPE_NOT_SPECIFIED, + ID_TYPE_UID, + ID_TYPE_GID, +- ID_TYPE_BOTH ++ ID_TYPE_BOTH, ++ /* ++ * This are internal between winbindd ++ * parent and child. ++ * ++ * It means the idmap backend/child requires a valid type_hint ++ * for wbint_Sids2UnixIDs(): ++ * ++ * - ID_TYPE_UID or ID_TYPE_GID means the user/group exists ++ * - ID_TYPE_BOTH means that only the domain exist ++ */ ++ ID_TYPE_WB_REQUIRE_TYPE + } id_type; + + typedef [public] struct { +@@ -23,7 +34,15 @@ interface idmap + ID_UNKNOWN, + ID_MAPPED, + ID_UNMAPPED, +- ID_EXPIRED ++ ID_EXPIRED, ++ /* ++ * This means the idmap backend requires a valid type_hint ++ * in order to map a sid to a unix id. ++ * ++ * - ID_TYPE_UID or ID_TYPE_GID means the user/group exists ++ * - ID_TYPE_BOTH means that only the domain exist ++ */ ++ ID_REQUIRE_TYPE + } id_mapping; + + typedef [public] struct { +-- +2.23.0 + diff --git a/backport-0007-CVE-2020-25717-s3-idmap_hash-reliable-return-ID_TYPE.patch b/backport-0007-CVE-2020-25717-s3-idmap_hash-reliable-return-ID_TYPE.patch new file mode 100644 index 0000000..f09de4f --- /dev/null +++ b/backport-0007-CVE-2020-25717-s3-idmap_hash-reliable-return-ID_TYPE.patch @@ -0,0 +1,104 @@ +From 4925a110c4e0586ca74566beca2450bbc4d18e4c Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 23 Oct 2020 12:21:57 +0200 +Subject: [PATCH 029/266] CVE-2020-25717 s3:idmap_hash: reliable return + ID_TYPE_BOTH + +idmap_hash used to bounce back the requested type, +which was ID_TYPE_UID, ID_TYPE_GID or ID_TYPE_NOT_SPECIFIED +before as the winbindd parent always used a lookupsids. +When the lookupsids failed because of an unknown domain, +the idmap child weren't requested at all and the caller +sees ID_TYPE_NOT_SPECIFIED. + +This module should have supported ID_TYPE_BOTH since +samba-4.1.0, similar to idmap_rid and idmap_autorid. + +Now that the winbindd parent will pass ID_TYPE_BOTH in order to +indicate that the domain exists, it's better to always return +ID_TYPE_BOTH instead of a random mix of ID_TYPE_UID, ID_TYPE_GID +or ID_TYPE_BOTH. In order to request a type_hint it will return +ID_REQUIRE_TYPE for ID_TYPE_NOT_SPECIFIED, which means that +the parent at least assures that the domain sid exists. +And the caller still gets ID_TYPE_NOT_SPECIFIED if the +domain doesn't exist. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14539 + +Signed-off-by: Stefan Metzmacher + +Autobuild-User(master): Stefan Metzmacher +Autobuild-Date(master): Fri Jan 22 11:32:46 UTC 2021 on sn-devel-184 + +(cherry picked from commit d8339056eef2845805f573bd8b0f3323370ecc8f) +Reviewed-by: Ralph Boehme + +Autobuild-User(v4-14-test): Karolin Seeger +Autobuild-Date(v4-14-test): Wed Jan 27 17:06:51 UTC 2021 on sn-devel-184 + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +(cherry picked from commit 99673b77b069674a6145552eb870de8829dfa503) +--- + source3/winbindd/idmap_hash/idmap_hash.c | 35 ++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=4925a110c4e0586ca74566beca2450bbc4d18e4c + +diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c +index be0ba45a044..d0bed7631a6 100644 +--- a/source3/winbindd/idmap_hash/idmap_hash.c ++++ b/source3/winbindd/idmap_hash/idmap_hash.c +@@ -261,6 +261,25 @@ static NTSTATUS sids_to_unixids(struct idmap_domain *dom, + + ids[i]->status = ID_UNMAPPED; + ++ if (ids[i]->xid.type == ID_TYPE_NOT_SPECIFIED) { ++ /* ++ * idmap_hash used to bounce back the requested type, ++ * which was ID_TYPE_UID, ID_TYPE_GID or ++ * ID_TYPE_NOT_SPECIFIED before as the winbindd parent ++ * always used a lookupsids. When the lookupsids ++ * failed because of an unknown domain, the idmap child ++ * weren't requested at all and the caller sees ++ * ID_TYPE_NOT_SPECIFIED. ++ * ++ * Now that the winbindd parent will pass ID_TYPE_BOTH ++ * in order to indicate that the domain exists. ++ * We should ask the parent to fallback to lookupsids ++ * if the domain is not known yet. ++ */ ++ ids[i]->status = ID_REQUIRE_TYPE; ++ continue; ++ } ++ + sid_copy(&sid, ids[i]->sid); + sid_split_rid(&sid, &rid); + +@@ -270,6 +289,22 @@ static NTSTATUS sids_to_unixids(struct idmap_domain *dom, + /* Check that both hashes are non-zero*/ + + if (h_domain && h_rid) { ++ /* ++ * idmap_hash used to bounce back the requested type, ++ * which was ID_TYPE_UID, ID_TYPE_GID or ++ * ID_TYPE_NOT_SPECIFIED before as the winbindd parent ++ * always used a lookupsids. ++ * ++ * This module should have supported ID_TYPE_BOTH since ++ * samba-4.1.0, similar to idmap_rid and idmap_autorid. ++ * ++ * Now that the winbindd parent will pass ID_TYPE_BOTH ++ * in order to indicate that the domain exists, it's ++ * better to always return ID_TYPE_BOTH instead of a ++ * random mix of ID_TYPE_UID, ID_TYPE_GID or ++ * ID_TYPE_BOTH. ++ */ ++ ids[i]->xid.type = ID_TYPE_BOTH; + ids[i]->xid.id = combine_hashes(h_domain, h_rid); + ids[i]->status = ID_MAPPED; + } +-- +2.23.0 + diff --git a/backport-0008-CVE-2020-25717-winbindd-call-wb_parent_idmap_setup_s.patch b/backport-0008-CVE-2020-25717-winbindd-call-wb_parent_idmap_setup_s.patch new file mode 100644 index 0000000..8d8816e --- /dev/null +++ b/backport-0008-CVE-2020-25717-winbindd-call-wb_parent_idmap_setup_s.patch @@ -0,0 +1,81 @@ +From 4a68c748e47e906f0d812a1572168e677afc1eb4 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 31 Aug 2021 17:04:56 +0200 +Subject: [PATCH 030/266] CVE-2020-25717 winbindd: call + wb_parent_idmap_setup_send() in wb_queryuser_send() + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14804 + +Signed-off-by: Ralph Boehme +Reviewed-by: Volker Lendecke +(cherry picked from commit 39c2ec72cb77945c3eb611fb1d7d7e9aad52bdfd) + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +(cherry picked from commit 7d1dd87a6538f8c7f1e4938b0ff52cbd231fff90) +--- + source3/winbindd/wb_queryuser.c | 30 +++++++++++++++++++++++++++--- + 1 file changed, 27 insertions(+), 3 deletions(-) + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=4a68c748e47e906f0d812a1572168e677afc1eb4 + +diff --git a/source3/winbindd/wb_queryuser.c b/source3/winbindd/wb_queryuser.c +index 9db51909c02..f5bc96f03f6 100644 +--- a/source3/winbindd/wb_queryuser.c ++++ b/source3/winbindd/wb_queryuser.c +@@ -25,10 +25,12 @@ + + struct wb_queryuser_state { + struct tevent_context *ev; +- struct wbint_userinfo *info; ++ struct wbint_userinfo *info; ++ const struct wb_parent_idmap_config *idmap_cfg; + bool tried_dclookup; + }; + ++static void wb_queryuser_idmap_setup_done(struct tevent_req *subreq); + static void wb_queryuser_got_uid(struct tevent_req *subreq); + static void wb_queryuser_got_domain(struct tevent_req *subreq); + static void wb_queryuser_got_dc(struct tevent_req *subreq); +@@ -60,13 +62,35 @@ struct tevent_req *wb_queryuser_send(TALLOC_CTX *mem_ctx, + + sid_copy(&info->user_sid, user_sid); + ++ 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_queryuser_idmap_setup_done, req); ++ return req; ++} ++ ++static void wb_queryuser_idmap_setup_done(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = tevent_req_callback_data( ++ subreq, struct tevent_req); ++ struct wb_queryuser_state *state = tevent_req_data( ++ req, struct wb_queryuser_state); ++ NTSTATUS status; ++ ++ status = wb_parent_idmap_setup_recv(subreq, &state->idmap_cfg); ++ TALLOC_FREE(subreq); ++ if (tevent_req_nterror(req, status)) { ++ return; ++ } ++ + subreq = wb_sids2xids_send( + state, state->ev, &state->info->user_sid, 1); + if (tevent_req_nomem(subreq, req)) { +- return tevent_req_post(req, ev); ++ return; + } + tevent_req_set_callback(subreq, wb_queryuser_got_uid, req); +- return req; ++ return; + } + + static void wb_queryuser_got_uid(struct tevent_req *subreq) +-- +2.23.0 + diff --git a/backport-0009-CVE-2020-25717-winbind-ensure-wb_parent_idmap_setup_.patch b/backport-0009-CVE-2020-25717-winbind-ensure-wb_parent_idmap_setup_.patch new file mode 100644 index 0000000..37d2bb8 --- /dev/null +++ b/backport-0009-CVE-2020-25717-winbind-ensure-wb_parent_idmap_setup_.patch @@ -0,0 +1,109 @@ +From 4a39d8a1610b635760ac182be894d206eb0a1ee7 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 20 Aug 2021 15:04:49 +0200 +Subject: [PATCH 031/266] 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) +--- + source3/winbindd/winbindd_allocate_uid.c | 44 +++++++++++++++++++++--- + 1 file changed, 39 insertions(+), 5 deletions(-) + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=4a39d8a1610b635760ac182be894d206eb0a1ee7 + +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) +-- +2.23.0 + diff --git a/backport-0010-CVE-2020-25717-auth_sam-use-pdb_get_domain_info-to-l.patch b/backport-0010-CVE-2020-25717-auth_sam-use-pdb_get_domain_info-to-l.patch new file mode 100644 index 0000000..2a855d8 --- /dev/null +++ b/backport-0010-CVE-2020-25717-auth_sam-use-pdb_get_domain_info-to-l.patch @@ -0,0 +1,228 @@ +From eb4123b5caed6c5cbfe8ef050f198e2d5a03f8b7 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Wed, 11 Nov 2020 14:42:55 +0200 +Subject: [PATCH 032/266] CVE-2020-25717 auth_sam: use pdb_get_domain_info to + look up DNS forest information + +When Samba is used as a part of FreeIPA domain controller, Windows +clients for a trusted AD forest may try to authenticate (perform logon +operation) as a REALM\name user account. + +Fix auth_sam plugins to accept DNS forest name if we are running on a DC +with PASSDB module providing domain information (e.g. pdb_get_domain_info() +returning non-NULL structure). Right now, only FreeIPA or Samba AD DC +PASSDB backends return this information but Samba AD DC configuration is +explicitly ignored by the two auth_sam (strict and netlogon3) modules. + +Detailed logs below: + +[2020/11/11 09:23:53.281296, 1, pid=42677, effective(65534, 65534), real(65534, 0), class=rpc_parse] ../../librpc/ndr/ndr.c:482(ndr_print_function_debug) + netr_LogonSamLogonWithFlags: struct netr_LogonSamLogonWithFlags + in: struct netr_LogonSamLogonWithFlags + server_name : * + server_name : '\\master.ipa.test' + computer_name : * + computer_name : 'AD1' + credential : * + credential: struct netr_Authenticator + cred: struct netr_Credential + data : 529f4b087c5f6546 + timestamp : Wed Nov 11 09:23:55 AM 2020 UTC + return_authenticator : * + return_authenticator: struct netr_Authenticator + cred: struct netr_Credential + data : 204f28f622010000 + timestamp : Fri May 2 06:37:50 AM 1986 UTC + logon_level : NetlogonNetworkTransitiveInformation (6) + logon : * + logon : union netr_LogonLevel(case 6) + network : * + network: struct netr_NetworkInfo + identity_info: struct netr_IdentityInfo + domain_name: struct lsa_String + length : 0x0010 (16) + size : 0x01fe (510) + string : * + string : 'IPA.TEST' + parameter_control : 0x00002ae0 (10976) + 0: MSV1_0_CLEARTEXT_PASSWORD_ALLOWED + 0: MSV1_0_UPDATE_LOGON_STATISTICS + 0: MSV1_0_RETURN_USER_PARAMETERS + 0: MSV1_0_DONT_TRY_GUEST_ACCOUNT + 1: MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT + 1: MSV1_0_RETURN_PASSWORD_EXPIRY + 1: MSV1_0_USE_CLIENT_CHALLENGE + 0: MSV1_0_TRY_GUEST_ACCOUNT_ONLY + 1: MSV1_0_RETURN_PROFILE_PATH + 0: MSV1_0_TRY_SPECIFIED_DOMAIN_ONLY + 1: MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT + 0: MSV1_0_DISABLE_PERSONAL_FALLBACK + 1: MSV1_0_ALLOW_FORCE_GUEST + 0: MSV1_0_CLEARTEXT_PASSWORD_SUPPLIED + 0: MSV1_0_USE_DOMAIN_FOR_ROUTING_ONLY + 0: MSV1_0_ALLOW_MSVCHAPV2 + 0: MSV1_0_S4U2SELF + 0: MSV1_0_CHECK_LOGONHOURS_FOR_S4U + 0: MSV1_0_SUBAUTHENTICATION_DLL_EX + logon_id : 0x0000000000884ef2 (8933106) + account_name: struct lsa_String + length : 0x000e (14) + size : 0x000e (14) + string : * + string : 'idmuser' + workstation: struct lsa_String + length : 0x0000 (0) + size : 0x0000 (0) + string : * + string : '' + challenge : 417207867bd33c74 + nt: struct netr_ChallengeResponse + length : 0x00c0 (192) + size : 0x00c0 (192) + data : * + data: ARRAY(192) + [0000] A5 24 62 6E 31 DF 69 66 9E DC 54 D6 63 4C D6 2F .$bn1.if ..T.cL./ + [0010] 01 01 00 00 00 00 00 00 50 37 D7 60 0C B8 D6 01 ........ P7.`.... + [0020] 15 1B 38 4F 47 95 4D 62 00 00 00 00 02 00 0E 00 ..8OG.Mb ........ + [0030] 57 00 49 00 4E 00 32 00 30 00 31 00 36 00 01 00 W.I.N.2. 0.1.6... + [0040] 06 00 41 00 44 00 31 00 04 00 18 00 77 00 69 00 ..A.D.1. ....w.i. + [0050] 6E 00 32 00 30 00 31 00 36 00 2E 00 74 00 65 00 n.2.0.1. 6...t.e. + [0060] 73 00 74 00 03 00 20 00 61 00 64 00 31 00 2E 00 s.t... . a.d.1... + [0070] 77 00 69 00 6E 00 32 00 30 00 31 00 36 00 2E 00 w.i.n.2. 0.1.6... + [0080] 74 00 65 00 73 00 74 00 05 00 18 00 77 00 69 00 t.e.s.t. ....w.i. + [0090] 6E 00 32 00 30 00 31 00 36 00 2E 00 74 00 65 00 n.2.0.1. 6...t.e. + [00A0] 73 00 74 00 07 00 08 00 50 37 D7 60 0C B8 D6 01 s.t..... P7.`.... + [00B0] 06 00 04 00 02 00 00 00 00 00 00 00 00 00 00 00 ........ ........ + lm: struct netr_ChallengeResponse + length : 0x0018 (24) + size : 0x0018 (24) + data : * + data : 000000000000000000000000000000000000000000000000 + validation_level : 0x0006 (6) + flags : * + flags : 0x00000000 (0) + 0: NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT + 0: NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP + 0: NETLOGON_SAMLOGON_FLAG_RODC_TO_OTHER_DOMAIN + 0: NETLOGON_SAMLOGON_FLAG_RODC_NTLM_REQUEST + +In such case checks for a workgroup name will not match the DNS forest +name used in the username specification: + +[2020/11/11 09:23:53.283055, 3, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth.c:200(auth_check_ntlm_password) + check_ntlm_password: Checking password for unmapped user [IPA.TEST]\[idmuser]@[] with the new password interface +[2020/11/11 09:23:53.283073, 3, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth.c:203(auth_check_ntlm_password) + check_ntlm_password: mapped user is: [IPA.TEST]\[idmuser]@[] +[2020/11/11 09:23:53.283082, 10, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth.c:213(auth_check_ntlm_password) + check_ntlm_password: auth_context challenge created by fixed +[2020/11/11 09:23:53.283091, 10, pid=42677, effective(65534, 65534), real(65534, 0), class=auth] ../../source3/auth/auth.c:216(auth_check_ntlm_password) + challenge is: +[2020/11/11 09:23:53.283099, 5, pid=42677, effective(65534, 65534), real(65534, 0)] ../../lib/util/util.c:678(dump_data) + [0000] 41 72 07 86 7B D3 3C 74 Ar..{. +Reviewed-by: Andreas Schneider + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +(cherry picked from commit 2a8b672652dcbcf55ec59be537773d76f0f14d0a) +--- + source3/auth/auth_sam.c | 45 +++++++++++++++++++++++++++++++++++++---- + 1 file changed, 41 insertions(+), 4 deletions(-) + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=eb4123b5caed6c5cbfe8ef050f198e2d5a03f8b7 + +diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c +index 3c12f959faf..e8e0d543f8c 100644 +--- a/source3/auth/auth_sam.c ++++ b/source3/auth/auth_sam.c +@@ -22,6 +22,7 @@ + + #include "includes.h" + #include "auth.h" ++#include "passdb.h" + + #undef DBGC_CLASS + #define DBGC_CLASS DBGC_AUTH +@@ -142,10 +143,28 @@ static NTSTATUS auth_samstrict_auth(const struct auth_context *auth_context, + break; + case ROLE_DOMAIN_PDC: + case ROLE_DOMAIN_BDC: +- if ( !is_local_name && !is_my_domain ) { +- DEBUG(6,("check_samstrict_security: %s is not one of my local names or domain name (DC)\n", +- effective_domain)); +- return NT_STATUS_NOT_IMPLEMENTED; ++ if (!is_local_name && !is_my_domain) { ++ /* If we are running on a DC that has PASSDB module with domain ++ * information, check if DNS forest name is matching the domain ++ * name. This is the case of FreeIPA domain controller when ++ * trusted AD DCs attempt to authenticate FreeIPA users using ++ * the forest root domain (which is the only domain in FreeIPA). ++ */ ++ struct pdb_domain_info *dom_info = NULL; ++ ++ dom_info = pdb_get_domain_info(mem_ctx); ++ if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) { ++ is_my_domain = strequal(user_info->mapped.domain_name, ++ dom_info->dns_forest); ++ } ++ ++ TALLOC_FREE(dom_info); ++ if (!is_my_domain) { ++ DEBUG(6,("check_samstrict_security: %s is not one " ++ "of my local names or domain name (DC)\n", ++ effective_domain)); ++ return NT_STATUS_NOT_IMPLEMENTED; ++ } + } + + break; +@@ -230,6 +249,24 @@ static NTSTATUS auth_sam_netlogon3_auth(const struct auth_context *auth_context, + } + + is_my_domain = strequal(user_info->mapped.domain_name, lp_workgroup()); ++ if (!is_my_domain) { ++ /* If we are running on a DC that has PASSDB module with domain ++ * information, check if DNS forest name is matching the domain ++ * name. This is the case of FreeIPA domain controller when ++ * trusted AD DCs attempt to authenticate FreeIPA users using ++ * the forest root domain (which is the only domain in FreeIPA). ++ */ ++ struct pdb_domain_info *dom_info = NULL; ++ dom_info = pdb_get_domain_info(mem_ctx); ++ ++ if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) { ++ is_my_domain = strequal(user_info->mapped.domain_name, ++ dom_info->dns_forest); ++ } ++ ++ TALLOC_FREE(dom_info); ++ } ++ + if (!is_my_domain) { + DBG_INFO("%s is not our domain name (DC for %s)\n", + effective_domain, lp_workgroup()); +-- +2.23.0 + diff --git a/backport-0011-CVE-2020-25717-s3-winbindd-make-sure-we-default-to-r.patch b/backport-0011-CVE-2020-25717-s3-winbindd-make-sure-we-default-to-r.patch new file mode 100644 index 0000000..a1bbe6c --- /dev/null +++ b/backport-0011-CVE-2020-25717-s3-winbindd-make-sure-we-default-to-r.patch @@ -0,0 +1,176 @@ +From 5966f8c2d47ed0d6544d7ac242bcbe2c849b474e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 4 Oct 2021 17:29:34 +0200 +Subject: [PATCH 103/266] CVE-2020-25717: s3:winbindd: make sure we default to + r->out.authoritative = true + +We need to make sure that temporary failures don't trigger a fallback +to the local SAM that silently ignores the domain name part for users. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +--- + source3/winbindd/winbindd_dual_srv.c | 7 +++++++ + source3/winbindd/winbindd_irpc.c | 7 +++++++ + source3/winbindd/winbindd_pam.c | 15 +++++++++++---- + source3/winbindd/winbindd_pam_auth_crap.c | 9 ++++++++- + source3/winbindd/winbindd_util.c | 7 +++++++ + 5 files changed, 40 insertions(+), 4 deletions(-) + +Conflict:{ --> unsigned char local_nt_response[24]; +delete a chunk from previos commit we don't introduce +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=5966f8c2d47ed0d6544d7ac242bcbe2c849b474e + +diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c +index 4a4894c2658..078fa77aed6 100644 +--- a/source3/winbindd/winbindd_dual_srv.c ++++ b/source3/winbindd/winbindd_dual_srv.c +@@ -940,6 +940,13 @@ NTSTATUS _winbind_SamLogon(struct pipes_struct *p, + union netr_Validation *validation = NULL; + bool interactive = false; + ++ /* ++ * Make sure we start with authoritative=true, ++ * it will only set to false if we don't know the ++ * domain. ++ */ ++ r->out.authoritative = true; ++ + domain = wb_child_domain(); + if (domain == NULL) { + return NT_STATUS_REQUEST_NOT_ACCEPTED; +diff --git a/source3/winbindd/winbindd_irpc.c b/source3/winbindd/winbindd_irpc.c +index fda29c7e702..12f4554f9b6 100644 +--- a/source3/winbindd/winbindd_irpc.c ++++ b/source3/winbindd/winbindd_irpc.c +@@ -141,6 +141,13 @@ static NTSTATUS wb_irpc_SamLogon(struct irpc_message *msg, + const char *target_domain_name = NULL; + const char *account_name = NULL; + ++ /* ++ * Make sure we start with authoritative=true, ++ * it will only set to false if we don't know the ++ * domain. ++ */ ++ req->out.authoritative = true; ++ + switch (req->in.logon_level) { + case NetlogonInteractiveInformation: + case NetlogonServiceInformation: +diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c +index c49033b375d..59dd18e27b8 100644 +--- a/source3/winbindd/winbindd_pam.c ++++ b/source3/winbindd/winbindd_pam.c +@@ -1797,7 +1797,7 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon( + unsigned char local_nt_response[24]; + fstring name_namespace, name_domain, name_user; + NTSTATUS result; +- uint8_t authoritative = 0; ++ uint8_t authoritative = 1; + uint32_t flags = 0; + uint16_t validation_level = 0; + union netr_Validation *validation = NULL; +@@ -2451,6 +2451,13 @@ done: + result = NT_STATUS_NO_LOGON_SERVERS; + } + ++ /* ++ * Here we don't alter ++ * state->response->data.auth.authoritative based ++ * on the servers response ++ * as we don't want a fallback to the local sam ++ * for interactive PAM logons ++ */ + set_auth_errors(state->response, result); + + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", +@@ -2665,7 +2672,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, + const char *name_domain = NULL; + const char *workstation; + uint64_t logon_id = 0; +- uint8_t authoritative = 0; ++ uint8_t authoritative = 1; + uint32_t flags = 0; + uint16_t validation_level; + union netr_Validation *validation = NULL; +@@ -2738,7 +2745,6 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, + &validation_level, + &validation); + if (!NT_STATUS_IS_OK(result)) { +- state->response->data.auth.authoritative = authoritative; + goto done; + } + +@@ -2792,6 +2797,8 @@ done: + } + + set_auth_errors(state->response, result); ++ state->response->data.auth.authoritative = authoritative; ++ + /* + * Log the winbind pam authentication, the logon_id will tie this to + * any of the logons invoked from this request. +diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c +index b7912db43df..40cab81b5ea 100644 +--- a/source3/winbindd/winbindd_pam_auth_crap.c ++++ b/source3/winbindd/winbindd_pam_auth_crap.c +@@ -24,6 +24,7 @@ + + struct winbindd_pam_auth_crap_state { + struct winbindd_response *response; ++ bool authoritative; + uint32_t flags; + }; + +@@ -45,7 +46,7 @@ struct tevent_req *winbindd_pam_auth_crap_send( + if (req == NULL) { + return NULL; + } +- ++ state->authoritative = true; + state->flags = request->flags; + + if (state->flags & WBFLAG_PAM_AUTH_PAC) { +@@ -124,6 +125,11 @@ struct tevent_req *winbindd_pam_auth_crap_send( + + domain = find_auth_domain(request->flags, auth_domain); + if (domain == NULL) { ++ /* ++ * We don't know the domain so ++ * we're not authoritative ++ */ ++ state->authoritative = false; + tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); + return tevent_req_post(req, ev); + } +@@ -184,6 +190,7 @@ NTSTATUS winbindd_pam_auth_crap_recv(struct tevent_req *req, + + if (tevent_req_is_nterror(req, &status)) { + set_auth_errors(response, status); ++ response->data.auth.authoritative = state->authoritative; + return status; + } + +diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c +index bec706f87de..ef197310fa0 100644 +--- a/source3/winbindd/winbindd_util.c ++++ b/source3/winbindd/winbindd_util.c +@@ -2092,6 +2092,13 @@ void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain) + + void set_auth_errors(struct winbindd_response *resp, NTSTATUS result) + { ++ /* ++ * Make sure we start with authoritative=true, ++ * it will only set to false if we don't know the ++ * domain. ++ */ ++ resp->data.auth.authoritative = true; ++ + resp->data.auth.nt_status = NT_STATUS_V(result); + fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result)); + +-- +2.23.0 + diff --git a/backport-0012-CVE-2020-25717-s4-auth-ntlm-make-sure-auth_check_pas.patch b/backport-0012-CVE-2020-25717-s4-auth-ntlm-make-sure-auth_check_pas.patch new file mode 100644 index 0000000..062684b --- /dev/null +++ b/backport-0012-CVE-2020-25717-s4-auth-ntlm-make-sure-auth_check_pas.patch @@ -0,0 +1,39 @@ +From 66cd97e558cdb57bff2dfc2bf8734b0ee12f648e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 4 Oct 2021 17:29:34 +0200 +Subject: [PATCH 104/266] CVE-2020-25717: s4:auth/ntlm: make sure + auth_check_password() defaults to r->out.authoritative = true + +We need to make sure that temporary failures don't trigger a fallback +to the local SAM that silently ignores the domain name part for users. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +--- + source4/auth/ntlm/auth.c | 5 +++++ + 1 file changed, 5 insertions(+) + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=66cd97e558cdb57bff2dfc2bf8734b0ee12f648e + +diff --git a/source4/auth/ntlm/auth.c b/source4/auth/ntlm/auth.c +index 1aa2e3b065f..e0c4436343c 100644 +--- a/source4/auth/ntlm/auth.c ++++ b/source4/auth/ntlm/auth.c +@@ -169,6 +169,11 @@ _PUBLIC_ NTSTATUS auth_check_password(struct auth4_context *auth_ctx, + /*TODO: create a new event context here! */ + ev = auth_ctx->event_ctx; + ++ /* ++ * We are authoritative by default ++ */ ++ *pauthoritative = 1; ++ + subreq = auth_check_password_send(mem_ctx, + ev, + auth_ctx, +-- +2.23.0 + diff --git a/backport-0013-CVE-2020-25717-loadparm-Add-new-parameter-min-domain.patch b/backport-0013-CVE-2020-25717-loadparm-Add-new-parameter-min-domain.patch new file mode 100644 index 0000000..70745c7 --- /dev/null +++ b/backport-0013-CVE-2020-25717-loadparm-Add-new-parameter-min-domain.patch @@ -0,0 +1,101 @@ +From b9d8f8025b7122cab64c37e5042866c66b556016 Mon Sep 17 00:00:00 2001 +From: Samuel Cabrero +Date: Tue, 28 Sep 2021 10:43:40 +0200 +Subject: [PATCH 113/266] CVE-2020-25717: loadparm: Add new parameter "min + domain uid" + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +Pair-Programmed-With: Stefan Metzmacher + +Signed-off-by: Samuel Cabrero +Signed-off-by: Stefan Metzmacher + +[abartlet@samba.org Backported from master/4.15 due to + conflicts with other new parameters] +--- + docs-xml/smbdotconf/security/mindomainuid.xml | 17 +++++++++++++++++ + docs-xml/smbdotconf/winbind/idmapconfig.xml | 4 ++++ + lib/param/loadparm.c | 4 ++++ + source3/param/loadparm.c | 2 ++ + 4 files changed, 27 insertions(+) + create mode 100644 docs-xml/smbdotconf/security/mindomainuid.xml + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=b9d8f8025b7122cab64c37e5042866c66b556016 + +diff --git a/docs-xml/smbdotconf/security/mindomainuid.xml b/docs-xml/smbdotconf/security/mindomainuid.xml +new file mode 100644 +index 00000000000..46ae795d730 +--- /dev/null ++++ b/docs-xml/smbdotconf/security/mindomainuid.xml +@@ -0,0 +1,17 @@ ++ ++ ++ ++ The integer parameter specifies the minimum uid allowed when mapping a ++ local account to a domain account. ++ ++ ++ ++ Note that this option interacts with the configured idmap ranges! ++ ++ ++ ++1000 ++ +diff --git a/docs-xml/smbdotconf/winbind/idmapconfig.xml b/docs-xml/smbdotconf/winbind/idmapconfig.xml +index 1374040fb29..f70f11df757 100644 +--- a/docs-xml/smbdotconf/winbind/idmapconfig.xml ++++ b/docs-xml/smbdotconf/winbind/idmapconfig.xml +@@ -80,6 +80,9 @@ + authoritative for a unix ID to SID mapping, so it must be set + for each individually configured domain and for the default + configuration. The configured ranges must be mutually disjoint. ++ ++ ++ Note that the low value interacts with the option! + + + +@@ -115,4 +118,5 @@ + + + ++min domain uid + +diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c +index 006caabc092..d2f6e6241ad 100644 +--- a/lib/param/loadparm.c ++++ b/lib/param/loadparm.c +@@ -3079,6 +3079,10 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) + lpcfg_do_global_parameter( + lp_ctx, "ldap max search request size", "256000"); + ++ lpcfg_do_global_parameter(lp_ctx, ++ "min domain uid", ++ "1000"); ++ + for (i = 0; parm_table[i].label; i++) { + if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) { + lp_ctx->flags[i] |= FLAG_DEFAULT; +diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c +index a3abaa2ec67..301e3622ed4 100644 +--- a/source3/param/loadparm.c ++++ b/source3/param/loadparm.c +@@ -960,6 +960,8 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) + Globals.ldap_max_authenticated_request_size = 16777216; + Globals.ldap_max_search_request_size = 256000; + ++ Globals.min_domain_uid = 1000; ++ + /* Now put back the settings that were set with lp_set_cmdline() */ + apply_lp_set_cmdline(); + } +-- +2.23.0 + diff --git a/backport-0014-CVE-2020-25717-s3-auth-Check-minimum-domain-uid.patch b/backport-0014-CVE-2020-25717-s3-auth-Check-minimum-domain-uid.patch new file mode 100644 index 0000000..86be4dd --- /dev/null +++ b/backport-0014-CVE-2020-25717-s3-auth-Check-minimum-domain-uid.patch @@ -0,0 +1,53 @@ +From ce47a81eb5f79dd3f54b300f6a9a7ccac9c1296a Mon Sep 17 00:00:00 2001 +From: Samuel Cabrero +Date: Tue, 28 Sep 2021 10:45:11 +0200 +Subject: [PATCH 117/266] CVE-2020-25717: s3:auth: Check minimum domain uid + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +Pair-Programmed-With: Stefan Metzmacher + +Signed-off-by: Samuel Cabrero +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett + +[abartlet@samba.org Removed knownfail on advice from metze] +--- + source3/auth/auth_util.c | 16 ++++++++++++++++ + 1 files changed, 16 insertions(+) + delete mode 100644 selftest/knownfail.d/min_domain_uid + +Conflict:delete a chunk which delete a file do not exist +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=ce47a81eb5f79dd3f54b300f6a9a7ccac9c1296a + +diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c +index 4686b29111e..4de4bc74374 100644 +--- a/source3/auth/auth_util.c ++++ b/source3/auth/auth_util.c +@@ -2103,6 +2103,22 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, + } + } + goto out; ++ } else if ((lp_security() == SEC_ADS || lp_security() == SEC_DOMAIN) && ++ !is_myname(domain) && pwd->pw_uid < lp_min_domain_uid()) { ++ /* ++ * !is_myname(domain) because when smbd starts tries to setup ++ * the guest user info, calling this function with nobody ++ * username. Nobody is usually uid 65535 but it can be changed ++ * to a regular user with 'guest account' parameter ++ */ ++ nt_status = NT_STATUS_INVALID_TOKEN; ++ DBG_NOTICE("Username '%s%s%s' is invalid on this system, " ++ "it does not meet 'min domain uid' " ++ "restriction (%u < %u): %s\n", ++ nt_domain, lp_winbind_separator(), nt_username, ++ pwd->pw_uid, lp_min_domain_uid(), ++ nt_errstr(nt_status)); ++ goto out; + } + + result = make_server_info(tmp_ctx); +-- +2.23.0 + diff --git a/backport-0015-CVE-2020-25717-s3-auth-we-should-not-try-to-autocrea.patch b/backport-0015-CVE-2020-25717-s3-auth-we-should-not-try-to-autocrea.patch new file mode 100644 index 0000000..f852ac6 --- /dev/null +++ b/backport-0015-CVE-2020-25717-s3-auth-we-should-not-try-to-autocrea.patch @@ -0,0 +1,36 @@ +From 885fe6e31b107b3a6362cde0785e6d886888e0ec Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 8 Oct 2021 17:40:30 +0200 +Subject: [PATCH 118/266] CVE-2020-25717: s3:auth: we should not try to + autocreate the guest account + +We should avoid autocreation of users as much as possible. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +--- + source3/auth/user_krb5.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=885fe6e31b107b3a6362cde0785e6d886888e0ec + +diff --git a/source3/auth/user_krb5.c b/source3/auth/user_krb5.c +index 8998f9c8f8a..074e8c7eb71 100644 +--- a/source3/auth/user_krb5.c ++++ b/source3/auth/user_krb5.c +@@ -155,7 +155,7 @@ NTSTATUS get_user_from_kerberos_info(TALLOC_CTX *mem_ctx, + if (!fuser) { + return NT_STATUS_NO_MEMORY; + } +- pw = smb_getpwnam(mem_ctx, fuser, &unixuser, true); ++ pw = smb_getpwnam(mem_ctx, fuser, &unixuser, false); + } + + /* extra sanity check that the guest account is valid */ +-- +2.23.0 + diff --git a/backport-0016-CVE-2020-25717-s3-auth-no-longer-let-check_account-a.patch b/backport-0016-CVE-2020-25717-s3-auth-no-longer-let-check_account-a.patch new file mode 100644 index 0000000..3adceb2 --- /dev/null +++ b/backport-0016-CVE-2020-25717-s3-auth-no-longer-let-check_account-a.patch @@ -0,0 +1,42 @@ +From d079628a43f845522598be7efa0abf5e478549c6 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 8 Oct 2021 18:08:20 +0200 +Subject: [PATCH 119/266] CVE-2020-25717: s3:auth: no longer let + check_account() autocreate local users + +So far we autocreated local user accounts based on just the +account_name (just ignoring any domain part). + +This only happens via a possible 'add user script', +which is not typically defined on domain members +and on NT4 DCs local users already exist in the +local passdb anyway. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +--- + source3/auth/auth_util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=d079628a43f845522598be7efa0abf5e478549c6 + +diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c +index 4de4bc74374..99b85d47a5f 100644 +--- a/source3/auth/auth_util.c ++++ b/source3/auth/auth_util.c +@@ -1898,7 +1898,7 @@ static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain, + return NT_STATUS_NO_MEMORY; + } + +- passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true ); ++ passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, false); + if (!passwd) { + DEBUG(3, ("Failed to find authenticated user %s via " + "getpwnam(), denying access.\n", dom_user)); +-- +2.23.0 + diff --git a/backport-0017-CVE-2020-25717-s3-auth-remove-fallbacks-in-smb_getpw.patch b/backport-0017-CVE-2020-25717-s3-auth-remove-fallbacks-in-smb_getpw.patch new file mode 100644 index 0000000..f01e4bb --- /dev/null +++ b/backport-0017-CVE-2020-25717-s3-auth-remove-fallbacks-in-smb_getpw.patch @@ -0,0 +1,181 @@ +From 844faf2f0ac5d21d65f452fb6f4d1b19bb0a2be2 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 8 Oct 2021 12:33:16 +0200 +Subject: [PATCH 120/266] CVE-2020-25717: s3:auth: remove fallbacks in + smb_getpwnam() + +So far we tried getpwnam("DOMAIN\account") first and +always did a fallback to getpwnam("account") completely +ignoring the domain part, this just causes problems +as we mix "DOMAIN1\account", "DOMAIN2\account", +and "account"! + +As we require a running winbindd for domain member setups +we should no longer do a fallback to just "account" for +users served by winbindd! + +For users of the local SAM don't use this code path, +as check_sam_security() doesn't call check_account(). + +The only case where smb_getpwnam("account") happens is +when map_username() via ("username map [script]") mapped +"DOMAIN\account" to something without '\', but that is +explicitly desired by the admin. + +Note: use 'git show -w' + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +Pair-Programmed-With: Stefan Metzmacher + +Signed-off-by: Ralph Boehme +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +--- + selftest/knownfail.d/ktest | 26 +++++++++++++ + source3/auth/auth_util.c | 77 +++++++++++++++++++++----------------- + 2 files changed, 68 insertions(+), 35 deletions(-) + create mode 100644 selftest/knownfail.d/ktest + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=844faf2f0ac5d21d65f452fb6f4d1b19bb0a2be2 + +diff --git a/selftest/knownfail.d/ktest b/selftest/knownfail.d/ktest +new file mode 100644 +index 00000000000..809612ba0b9 +--- /dev/null ++++ b/selftest/knownfail.d/ktest +@@ -0,0 +1,26 @@ ++^samba3.rpc.lsa.lookupsids.krb5.with.old.ccache.ncacn_np.with..smb2...lsa.LookupSidsReply.ktest ++^samba3.rpc.lsa.lookupsids.krb5.ncacn_np.with..smb2...lsa.LookupSidsReply.ktest ++^samba3.blackbox.rpcclient.krb5.ncacn_np.with..krb5...rpcclient.ktest:local ++^samba3.blackbox.rpcclient.krb5.ncacn_np.with..spnego,krb5...rpcclient.ktest:local ++^samba3.rpc.lsa.lookupsids.krb5.with.old.ccache.ncacn_np.with..smb2,connect...lsa.LookupSidsReply.ktest ++^samba3.rpc.lsa.lookupsids.krb5.ncacn_np.with..smb2,connect...lsa.LookupSidsReply.ktest ++^samba3.rpc.lsa.lookupsids.krb5.with.old.ccache.ncacn_np.with..smb2,packet...lsa.LookupSidsReply.ktest ++^samba3.rpc.lsa.lookupsids.krb5.ncacn_np.with..smb2,packet...lsa.LookupSidsReply.ktest ++^samba3.blackbox.rpcclient.krb5.ncacn_np.with..krb5,packet...rpcclient.ktest:local ++^samba3.blackbox.rpcclient.krb5.ncacn_np.with..spnego,krb5,packet...rpcclient.ktest:local ++^samba3.rpc.lsa.lookupsids.krb5.with.old.ccache.ncacn_np.with..smb2,sign...lsa.LookupSidsReply.ktest ++^samba3.rpc.lsa.lookupsids.krb5.ncacn_np.with..smb2,sign...lsa.LookupSidsReply.ktest ++^samba3.blackbox.rpcclient.krb5.ncacn_np.with..krb5,sign...rpcclient.ktest:local ++^samba3.blackbox.rpcclient.krb5.ncacn_np.with..spnego,krb5,sign...rpcclient.ktest:local ++^samba3.rpc.lsa.lookupsids.krb5.with.old.ccache.ncacn_np.with..smb2,seal...lsa.LookupSidsReply.ktest ++^samba3.rpc.lsa.lookupsids.krb5.ncacn_np.with..smb2,seal...lsa.LookupSidsReply.ktest ++^samba3.blackbox.rpcclient.krb5.ncacn_np.with..krb5,seal...rpcclient.ktest:local ++^samba3.blackbox.rpcclient.krb5.ncacn_np.with..spnego,krb5,seal...rpcclient.ktest:local ++^samba3.blackbox.smbclient_krb5.old.ccache..smbclient.ktest:local ++^samba3.blackbox.smbclient_krb5.new.ccache..smbclient.ktest:local ++^samba3.blackbox.smbclient_large_file..krb5.smbclient.large.posix.write.read.ktest:local ++^samba3.blackbox.smbclient_large_file..krb5.cmp.of.read.and.written.files.ktest:local ++^samba3.blackbox.smbclient_krb5.old.ccache.--client-protection=encrypt.smbclient.ktest:local ++^samba3.blackbox.smbclient_krb5.new.ccache.--client-protection=encrypt.smbclient.ktest:local ++^samba3.blackbox.smbclient_large_file.--client-protection=encrypt.krb5.smbclient.large.posix.write.read.ktest:local ++^samba3.blackbox.smbclient_large_file.--client-protection=encrypt.krb5.cmp.of.read.and.written.files.ktest:local +diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c +index 99b85d47a5f..d81313a0495 100644 +--- a/source3/auth/auth_util.c ++++ b/source3/auth/auth_util.c +@@ -1933,7 +1933,7 @@ struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser, + { + struct passwd *pw = NULL; + char *p = NULL; +- char *username = NULL; ++ const char *username = NULL; + + /* we only save a copy of the username it has been mangled + by winbindd use default domain */ +@@ -1952,48 +1952,55 @@ struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser, + /* code for a DOMAIN\user string */ + + if ( p ) { +- pw = Get_Pwnam_alloc( mem_ctx, domuser ); +- if ( pw ) { +- /* make sure we get the case of the username correct */ +- /* work around 'winbind use default domain = yes' */ +- +- if ( lp_winbind_use_default_domain() && +- !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) { +- char *domain; +- +- /* split the domain and username into 2 strings */ +- *p = '\0'; +- domain = username; +- +- *p_save_username = talloc_asprintf(mem_ctx, +- "%s%c%s", +- domain, +- *lp_winbind_separator(), +- pw->pw_name); +- if (!*p_save_username) { +- TALLOC_FREE(pw); +- return NULL; +- } +- } else { +- *p_save_username = talloc_strdup(mem_ctx, pw->pw_name); +- } ++ const char *domain = NULL; + +- /* whew -- done! */ +- return pw; ++ /* split the domain and username into 2 strings */ ++ *p = '\0'; ++ domain = username; ++ p++; ++ username = p; ++ ++ if (strequal(domain, get_global_sam_name())) { ++ /* ++ * This typically don't happen ++ * as check_sam_Security() ++ * don't call make_server_info_info3() ++ * and thus check_account(). ++ * ++ * But we better keep this. ++ */ ++ goto username_only; + } + +- /* setup for lookup of just the username */ +- /* remember that p and username are overlapping memory */ +- +- p++; +- username = talloc_strdup(mem_ctx, p); +- if (!username) { ++ pw = Get_Pwnam_alloc( mem_ctx, domuser ); ++ if (pw == NULL) { + return NULL; + } ++ /* make sure we get the case of the username correct */ ++ /* work around 'winbind use default domain = yes' */ ++ ++ if ( lp_winbind_use_default_domain() && ++ !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) { ++ *p_save_username = talloc_asprintf(mem_ctx, ++ "%s%c%s", ++ domain, ++ *lp_winbind_separator(), ++ pw->pw_name); ++ if (!*p_save_username) { ++ TALLOC_FREE(pw); ++ return NULL; ++ } ++ } else { ++ *p_save_username = talloc_strdup(mem_ctx, pw->pw_name); ++ } ++ ++ /* whew -- done! */ ++ return pw; ++ + } + + /* just lookup a plain username */ +- ++username_only: + pw = Get_Pwnam_alloc(mem_ctx, username); + + /* Create local user if requested but only if winbindd +-- +2.23.0 + diff --git a/backport-0018-CVE-2020-25717-s3-auth-don-t-let-create_local_token-.patch b/backport-0018-CVE-2020-25717-s3-auth-don-t-let-create_local_token-.patch new file mode 100644 index 0000000..1bef963 --- /dev/null +++ b/backport-0018-CVE-2020-25717-s3-auth-don-t-let-create_local_token-.patch @@ -0,0 +1,48 @@ +From e8e0bea9b333315ec1ff9eb1d36d4e810ca95941 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 4 Oct 2021 18:03:55 +0200 +Subject: [PATCH 122/266] CVE-2020-25717: s3:auth: don't let create_local_token + depend on !winbind_ping() + +We always require a running winbindd on a domain member, so +we should better fail a request instead of silently alter +the behaviour, which results in a different unix token, just +because winbindd might be restarted. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +--- + source3/auth/auth_util.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=e8e0bea9b333315ec1ff9eb1d36d4e810ca95941 + +diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c +index d81313a0495..065b525500f 100644 +--- a/source3/auth/auth_util.c ++++ b/source3/auth/auth_util.c +@@ -576,13 +576,11 @@ NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, + } + + /* +- * If winbind is not around, we can not make much use of the SIDs the +- * domain controller provided us with. Likewise if the user name was +- * mapped to some local unix user. ++ * If the user name was mapped to some local unix user, ++ * we can not make much use of the SIDs the ++ * domain controller provided us with. + */ +- +- if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) || +- (server_info->nss_token)) { ++ if (server_info->nss_token) { + char *found_username = NULL; + status = create_token_from_username(session_info, + server_info->unix_name, +-- +2.23.0 + diff --git a/backport-0019-CVE-2020-25719-CVE-2020-25717-auth-gensec-always-req.patch b/backport-0019-CVE-2020-25719-CVE-2020-25717-auth-gensec-always-req.patch new file mode 100644 index 0000000..fb6947f --- /dev/null +++ b/backport-0019-CVE-2020-25719-CVE-2020-25717-auth-gensec-always-req.patch @@ -0,0 +1,76 @@ +From eba5e1321830624e6e42d248616f651beb0d3b99 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 5 Oct 2021 18:11:57 +0200 +Subject: [PATCH 124/266] CVE-2020-25719 CVE-2020-25717: auth/gensec: always + require a PAC in domain mode (DC or member) + +AD domains always provide a PAC unless UF_NO_AUTH_DATA_REQUIRED is set +on the service account, which can only be explicitly configured, +but that's an invalid configuration! + +We still try to support standalone servers in an MIT realm, +as legacy setup. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett + +[jsutton@samba.org Removed knownfail entries] +--- + auth/gensec/gensec_util.c | 27 +++++++++++++++++++++++---- + 1 files changed, 23 insertions(+), 4 deletions(-) + delete mode 100644 selftest/knownfail.d/no-pac + +Conflict:delete a chunk which delete a file do not exist +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=eba5e1321830624e6e42d248616f651beb0d3b99 + +diff --git a/auth/gensec/gensec_util.c b/auth/gensec/gensec_util.c +index e185acc0c20..694661b53b5 100644 +--- a/auth/gensec/gensec_util.c ++++ b/auth/gensec/gensec_util.c +@@ -25,6 +25,8 @@ + #include "auth/gensec/gensec_internal.h" + #include "auth/common_auth.h" + #include "../lib/util/asn1.h" ++#include "param/param.h" ++#include "libds/common/roles.h" + + #undef DBGC_CLASS + #define DBGC_CLASS DBGC_AUTH +@@ -46,10 +48,27 @@ NTSTATUS gensec_generate_session_info_pac(TALLOC_CTX *mem_ctx, + session_info_flags |= AUTH_SESSION_INFO_DEFAULT_GROUPS; + + if (!pac_blob) { +- if (gensec_setting_bool(gensec_security->settings, "gensec", "require_pac", false)) { +- DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access\n", +- principal_string)); +- return NT_STATUS_ACCESS_DENIED; ++ enum server_role server_role = ++ lpcfg_server_role(gensec_security->settings->lp_ctx); ++ ++ /* ++ * For any domain setup (DC or member) we require having ++ * a PAC, as the service ticket comes from an AD DC, ++ * which will always provide a PAC, unless ++ * UF_NO_AUTH_DATA_REQUIRED is configured for our ++ * account, but that's just an invalid configuration, ++ * the admin configured for us! ++ * ++ * As a legacy case, we still allow kerberos tickets from an MIT ++ * realm, but only in standalone mode. In that mode we'll only ++ * ever accept a kerberos authentication with a keytab file ++ * being explicitly configured via the 'keytab method' option. ++ */ ++ if (server_role != ROLE_STANDALONE) { ++ DBG_WARNING("Unable to find PAC in ticket from %s, " ++ "failing to allow access\n", ++ principal_string); ++ return NT_STATUS_NO_IMPERSONATION_TOKEN; + } + DBG_NOTICE("Unable to find PAC for %s, resorting to local " + "user lookup\n", principal_string); +-- +2.23.0 + diff --git a/backport-0020-CVE-2020-25717-s3-ntlm_auth-fix-memory-leaks-in-ntlm.patch b/backport-0020-CVE-2020-25717-s3-ntlm_auth-fix-memory-leaks-in-ntlm.patch new file mode 100644 index 0000000..ac990fd --- /dev/null +++ b/backport-0020-CVE-2020-25717-s3-ntlm_auth-fix-memory-leaks-in-ntlm.patch @@ -0,0 +1,77 @@ +From 9f73360e17d1e519d25cb4b60d7506fca9fd02fe Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 21 Sep 2021 12:27:28 +0200 +Subject: [PATCH 126/266] CVE-2020-25717: s3:ntlm_auth: fix memory leaks in + ntlm_auth_generate_session_info_pac() + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +--- + source3/utils/ntlm_auth.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=9f73360e17d1e519d25cb4b60d7506fca9fd02fe + +diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c +index 1d22a48c57c..e6efdfcec5c 100644 +--- a/source3/utils/ntlm_auth.c ++++ b/source3/utils/ntlm_auth.c +@@ -817,23 +817,27 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c + if (!p) { + DEBUG(3, ("[%s] Doesn't look like a valid principal\n", + princ_name)); +- return NT_STATUS_LOGON_FAILURE; ++ status = NT_STATUS_LOGON_FAILURE; ++ goto done; + } + + user = talloc_strndup(mem_ctx, princ_name, p - princ_name); + if (!user) { +- return NT_STATUS_NO_MEMORY; ++ status = NT_STATUS_NO_MEMORY; ++ goto done; + } + + realm = talloc_strdup(talloc_tos(), p + 1); + if (!realm) { +- return NT_STATUS_NO_MEMORY; ++ status = NT_STATUS_NO_MEMORY; ++ goto done; + } + + if (!strequal(realm, lp_realm())) { + DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm)); + if (!lp_allow_trusted_domains()) { +- return NT_STATUS_LOGON_FAILURE; ++ status = NT_STATUS_LOGON_FAILURE; ++ goto done; + } + } + +@@ -841,7 +845,8 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c + domain = talloc_strdup(mem_ctx, + logon_info->info3.base.logon_domain.string); + if (!domain) { +- return NT_STATUS_NO_MEMORY; ++ status = NT_STATUS_NO_MEMORY; ++ goto done; + } + DEBUG(10, ("Domain is [%s] (using PAC)\n", domain)); + } else { +@@ -871,7 +876,8 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c + domain = talloc_strdup(mem_ctx, realm); + } + if (!domain) { +- return NT_STATUS_NO_MEMORY; ++ status = NT_STATUS_NO_MEMORY; ++ goto done; + } + DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain)); + } +-- +2.23.0 + diff --git a/backport-0021-CVE-2020-25717-s3-ntlm_auth-let-ntlm_auth_generate_s.patch b/backport-0021-CVE-2020-25717-s3-ntlm_auth-let-ntlm_auth_generate_s.patch new file mode 100644 index 0000000..66904b1 --- /dev/null +++ b/backport-0021-CVE-2020-25717-s3-ntlm_auth-let-ntlm_auth_generate_s.patch @@ -0,0 +1,145 @@ +From 131d5ceb9deaaa1d8dd478a9b2e2556133c511aa Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 21 Sep 2021 12:44:01 +0200 +Subject: [PATCH 127/266] CVE-2020-25717: s3:ntlm_auth: let + ntlm_auth_generate_session_info_pac() base the name on the PAC LOGON_INFO + only + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14801 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +--- + source3/utils/ntlm_auth.c | 91 ++++++++++++--------------------------- + 1 file changed, 28 insertions(+), 63 deletions(-) + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=131d5ceb9deaaa1d8dd478a9b2e2556133c511aa + +diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c +index e6efdfcec5c..5541c58350b 100644 +--- a/source3/utils/ntlm_auth.c ++++ b/source3/utils/ntlm_auth.c +@@ -789,10 +789,8 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c + struct PAC_LOGON_INFO *logon_info = NULL; + char *unixuser; + NTSTATUS status; +- char *domain = NULL; +- char *realm = NULL; +- char *user = NULL; +- char *p; ++ const char *domain = ""; ++ const char *user = ""; + + tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) { +@@ -809,79 +807,46 @@ static NTSTATUS ntlm_auth_generate_session_info_pac(struct auth4_context *auth_c + if (!NT_STATUS_IS_OK(status)) { + goto done; + } +- } +- +- DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name)); +- +- p = strchr_m(princ_name, '@'); +- if (!p) { +- DEBUG(3, ("[%s] Doesn't look like a valid principal\n", +- princ_name)); +- status = NT_STATUS_LOGON_FAILURE; ++ } else { ++ status = NT_STATUS_ACCESS_DENIED; ++ DBG_WARNING("Kerberos ticket for[%s] has no PAC: %s\n", ++ princ_name, nt_errstr(status)); + goto done; + } + +- user = talloc_strndup(mem_ctx, princ_name, p - princ_name); +- if (!user) { +- status = NT_STATUS_NO_MEMORY; +- goto done; ++ if (logon_info->info3.base.account_name.string != NULL) { ++ user = logon_info->info3.base.account_name.string; ++ } else { ++ user = ""; ++ } ++ if (logon_info->info3.base.logon_domain.string != NULL) { ++ domain = logon_info->info3.base.logon_domain.string; ++ } else { ++ domain = ""; + } + +- realm = talloc_strdup(talloc_tos(), p + 1); +- if (!realm) { +- status = NT_STATUS_NO_MEMORY; ++ if (strlen(user) == 0 || strlen(domain) == 0) { ++ status = NT_STATUS_ACCESS_DENIED; ++ DBG_WARNING("Kerberos ticket for[%s] has invalid " ++ "account_name[%s]/logon_domain[%s]: %s\n", ++ princ_name, ++ logon_info->info3.base.account_name.string, ++ logon_info->info3.base.logon_domain.string, ++ nt_errstr(status)); + goto done; + } + +- if (!strequal(realm, lp_realm())) { +- DEBUG(3, ("Ticket for foreign realm %s@%s\n", user, realm)); ++ DBG_NOTICE("Kerberos ticket principal name is [%s] " ++ "account_name[%s]/logon_domain[%s]\n", ++ princ_name, user, domain); ++ ++ if (!strequal(domain, lp_workgroup())) { + if (!lp_allow_trusted_domains()) { + status = NT_STATUS_LOGON_FAILURE; + goto done; + } + } + +- if (logon_info && logon_info->info3.base.logon_domain.string) { +- domain = talloc_strdup(mem_ctx, +- logon_info->info3.base.logon_domain.string); +- if (!domain) { +- status = NT_STATUS_NO_MEMORY; +- goto done; +- } +- DEBUG(10, ("Domain is [%s] (using PAC)\n", domain)); +- } else { +- +- /* If we have winbind running, we can (and must) shorten the +- username by using the short netbios name. Otherwise we will +- have inconsistent user names. With Kerberos, we get the +- fully qualified realm, with ntlmssp we get the short +- name. And even w2k3 does use ntlmssp if you for example +- connect to an ip address. */ +- +- wbcErr wbc_status; +- struct wbcDomainInfo *info = NULL; +- +- DEBUG(10, ("Mapping [%s] to short name using winbindd\n", +- realm)); +- +- wbc_status = wbcDomainInfo(realm, &info); +- +- if (WBC_ERROR_IS_OK(wbc_status)) { +- domain = talloc_strdup(mem_ctx, +- info->short_name); +- wbcFreeMemory(info); +- } else { +- DEBUG(3, ("Could not find short name: %s\n", +- wbcErrorString(wbc_status))); +- domain = talloc_strdup(mem_ctx, realm); +- } +- if (!domain) { +- status = NT_STATUS_NO_MEMORY; +- goto done; +- } +- DEBUG(10, ("Domain is [%s] (using Winbind)\n", domain)); +- } +- + unixuser = talloc_asprintf(tmp_ctx, "%s%c%s", domain, winbind_separator(), user); + if (!unixuser) { + status = NT_STATUS_NO_MEMORY; +-- +2.23.0 + diff --git a/backport-0022-use-set_current_user_info-in-auth3_generate_session_info_p.patch b/backport-0022-use-set_current_user_info-in-auth3_generate_session_info_p.patch new file mode 100644 index 0000000..9d04bbb --- /dev/null +++ b/backport-0022-use-set_current_user_info-in-auth3_generate_session_info_p.patch @@ -0,0 +1,52 @@ +From dc4b1e39ce1f2201a2d6ae2d4cffef2448f69a62 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Sat, 18 Jan 2020 08:06:45 +0100 +Subject: [PATCH] s3/auth: use set_current_user_info() in + auth3_generate_session_info_pac() + +This delays reloading config slightly, but I don't see how could affect +observable behaviour other then log messages coming from the functions in +between the different locations for lp_load_with_shares() like +make_session_info_krb5() are sent to a different logfile if "log file" uses %U. + +Signed-off-by: Ralph Boehme +Reviewed-by: Andreas Schneider +--- + source3/auth/auth_generic.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +Conflict:NA +Reference:https://github.com/samba-team/samba/commit/dc4b1e39ce1f2201a2d6ae2d4cffef2448f69a62 + +diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c +index 9243a0ba02d3..0e9500ac08d1 100644 +--- a/source3/auth/auth_generic.c ++++ b/source3/auth/auth_generic.c +@@ -159,12 +159,6 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + } + } + +- /* setup the string used by %U */ +- sub_set_smb_name(username); +- +- /* reload services so that the new %U is taken into account */ +- lp_load_with_shares(get_dyn_CONFIGFILE()); +- + status = make_session_info_krb5(mem_ctx, + ntuser, ntdomain, username, pw, + info3_copy, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, +@@ -176,6 +170,14 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + goto done; + } + ++ /* setup the string used by %U */ ++ set_current_user_info((*session_info)->unix_info->sanitized_username, ++ (*session_info)->unix_info->unix_name, ++ (*session_info)->info->domain_name); ++ ++ /* reload services so that the new %U is taken into account */ ++ lp_load_with_shares(get_dyn_CONFIGFILE()); ++ + DEBUG(5, (__location__ "OK: user: %s domain: %s client: %s\n", + ntuser, ntdomain, rhost)); + diff --git a/backport-0023-CVE-2020-25717-s3-auth-let-auth3_generate_session_in.patch b/backport-0023-CVE-2020-25717-s3-auth-let-auth3_generate_session_in.patch new file mode 100644 index 0000000..3316e2e --- /dev/null +++ b/backport-0023-CVE-2020-25717-s3-auth-let-auth3_generate_session_in.patch @@ -0,0 +1,319 @@ +From a152f36b0576737e647dbe5f1954039668123c1f Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Mon, 4 Oct 2021 19:42:20 +0200 +Subject: [PATCH 128/266] CVE-2020-25717: s3:auth: let + auth3_generate_session_info_pac() delegate everything to + make_server_info_wbcAuthUserInfo() + +This consolidates the code paths used for NTLMSSP and Kerberos! + +I checked what we were already doing for NTLMSSP, which is this: + +a) source3/auth/auth_winbind.c calls wbcAuthenticateUserEx() +b) as a domain member we require a valid response from winbindd, + otherwise we'll return NT_STATUS_NO_LOGON_SERVERS +c) we call make_server_info_wbcAuthUserInfo(), which internally + calls make_server_info_info3() +d) auth_check_ntlm_password() calls + smb_pam_accountcheck(unix_username, rhost), where rhost + is only an ipv4 or ipv6 address (without reverse dns lookup) +e) from auth3_check_password_send/auth3_check_password_recv() + server_returned_info will be passed to auth3_generate_session_info(), + triggered by gensec_session_info(), which means we'll call into + create_local_token() in order to transform auth_serversupplied_info + into auth_session_info. + +For Kerberos gensec_session_info() will call +auth3_generate_session_info_pac() via the gensec_generate_session_info_pac() +helper function. The current logic is this: + +a) gensec_generate_session_info_pac() is the function that + evaluates the 'gensec:require_pac', which defaulted to 'no' + before. +b) auth3_generate_session_info_pac() called + wbcAuthenticateUserEx() in order to pass the PAC blob + to winbindd, but only to prime its cache, e.g. netsamlogon cache + and others. Most failures were just ignored. +c) If the PAC blob is available, it extracted the PAC_LOGON_INFO + from it. +d) Then we called the horrible get_user_from_kerberos_info() function: + - It uses a first part of the tickets principal name (before the @) + as username and combines that with the 'logon_info->base.logon_domain' + if the logon_info (PAC) is present. + - As a fallback without a PAC it's tries to ask winbindd for a mapping + from realm to netbios domain name. + - Finally is falls back to using the realm as netbios domain name + With this information is builds 'userdomain+winbind_separator+useraccount' + and calls map_username() followed by smb_getpwnam() with create=true, + Note this is similar to the make_server_info_info3() => check_account() + => smb_getpwnam() logic under 3. + - It also calls smb_pam_accountcheck(), but may pass the reverse DNS lookup name + instead of the ip address as rhost. + - It does some MAP_TO_GUEST_ON_BAD_UID logic and auto creates the + guest account. +e) We called create_info3_from_pac_logon_info() +f) make_session_info_krb5() calls gets called and triggers this: + - If get_user_from_kerberos_info() mapped to guest, it calls + make_server_info_guest() + - If create_info3_from_pac_logon_info() created a info3 from logon_info, + it calls make_server_info_info3() + - Without a PAC it tries pdb_getsampwnam()/make_server_info_sam() with + a fallback to make_server_info_pw() + From there it calls create_local_token() + +I tried to change auth3_generate_session_info_pac() to behave similar +to auth_winbind.c together with auth3_generate_session_info() as +a domain member, as we now rely on a PAC: + +a) As domain member we require a PAC and always call wbcAuthenticateUserEx() + and require a valid response! +b) we call make_server_info_wbcAuthUserInfo(), which internally + calls make_server_info_info3(). Note make_server_info_info3() + handles MAP_TO_GUEST_ON_BAD_UID and make_server_info_guest() + internally. +c) Similar to auth_check_ntlm_password() we now call + smb_pam_accountcheck(unix_username, rhost), where rhost + is only an ipv4 or ipv6 address (without reverse dns lookup) +d) From there it calls create_local_token() + +As standalone server (in an MIT realm) we continue +with the already existing code logic, which works without a PAC: +a) we keep smb_getpwnam() with create=true logic as it + also requires an explicit 'add user script' option. +b) In the following commits we assert that there's + actually no PAC in this mode, which means we can + remove unused and confusing code. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14646 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett + +--- + source3/auth/auth_generic.c | 137 ++++++++++++++++++++++++++++-------- + 1 file changed, 109 insertions(+), 28 deletions(-) + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=a152f36b0576737e647dbe5f1954039668123c1f + +diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c +index 86585ad690c..450c358beeb 100644 +--- a/source3/auth/auth_generic.c ++++ b/source3/auth/auth_generic.c +@@ -46,6 +46,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + uint32_t session_info_flags, + struct auth_session_info **session_info) + { ++ enum server_role server_role = lp_server_role(); + TALLOC_CTX *tmp_ctx; + struct PAC_LOGON_INFO *logon_info = NULL; + struct netr_SamInfo3 *info3_copy = NULL; +@@ -54,39 +55,59 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + char *ntuser; + char *ntdomain; + char *username; +- char *rhost; ++ const char *rhost; + struct passwd *pw; + NTSTATUS status; +- int rc; + + tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) { + return NT_STATUS_NO_MEMORY; + } + +- if (pac_blob) { +-#ifdef HAVE_KRB5 ++ if (tsocket_address_is_inet(remote_address, "ip")) { ++ rhost = tsocket_address_inet_addr_string( ++ remote_address, tmp_ctx); ++ if (rhost == NULL) { ++ status = NT_STATUS_NO_MEMORY; ++ goto done; ++ } ++ } else { ++ rhost = "127.0.0.1"; ++ } ++ ++ if (server_role != ROLE_STANDALONE) { + struct wbcAuthUserParams params = {}; + struct wbcAuthUserInfo *info = NULL; + struct wbcAuthErrorInfo *err = NULL; ++ struct auth_serversupplied_info *server_info = NULL; ++ char *original_user_name = NULL; ++ char *p = NULL; + wbcErr wbc_err; + ++ if (pac_blob == NULL) { ++ /* ++ * This should already be catched at the main ++ * gensec layer, but better check twice ++ */ ++ status = NT_STATUS_INTERNAL_ERROR; ++ goto done; ++ } ++ + /* + * Let winbind decode the PAC. + * This will also store the user + * data in the netsamlogon cache. + * +- * We need to do this *before* we +- * call get_user_from_kerberos_info() +- * as that does a user lookup that +- * expects info in the netsamlogon cache. +- * +- * See BUG: https://bugzilla.samba.org/show_bug.cgi?id=11259 ++ * This used to be a cache prime ++ * optimization, but now we delegate ++ * all logic to winbindd, as we require ++ * winbindd as domain member anyway. + */ + params.level = WBC_AUTH_USER_LEVEL_PAC; + params.password.pac.data = pac_blob->data; + params.password.pac.length = pac_blob->length; + ++ /* we are contacting the privileged pipe */ + become_root(); + wbc_err = wbcAuthenticateUserEx(¶ms, &info, &err); + unbecome_root(); +@@ -99,18 +120,90 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + */ + + switch (wbc_err) { +- case WBC_ERR_WINBIND_NOT_AVAILABLE: + case WBC_ERR_SUCCESS: + break; ++ case WBC_ERR_WINBIND_NOT_AVAILABLE: ++ status = NT_STATUS_NO_LOGON_SERVERS; ++ DBG_ERR("winbindd not running - " ++ "but required as domain member: %s\n", ++ nt_errstr(status)); ++ goto done; + case WBC_ERR_AUTH_ERROR: + status = NT_STATUS(err->nt_status); + wbcFreeMemory(err); + goto done; ++ case WBC_ERR_NO_MEMORY: ++ status = NT_STATUS_NO_MEMORY; ++ goto done; + default: + status = NT_STATUS_LOGON_FAILURE; + goto done; + } + ++ status = make_server_info_wbcAuthUserInfo(tmp_ctx, ++ info->account_name, ++ info->domain_name, ++ info, &server_info); ++ if (!NT_STATUS_IS_OK(status)) { ++ DEBUG(10, ("make_server_info_wbcAuthUserInfo failed: %s\n", ++ nt_errstr(status))); ++ goto done; ++ } ++ ++ /* We skip doing this step if the caller asked us not to */ ++ if (!(server_info->guest)) { ++ const char *unix_username = server_info->unix_name; ++ ++ /* We might not be root if we are an RPC call */ ++ become_root(); ++ status = smb_pam_accountcheck(unix_username, rhost); ++ unbecome_root(); ++ ++ if (!NT_STATUS_IS_OK(status)) { ++ DEBUG(3, ("check_ntlm_password: PAM Account for user [%s] " ++ "FAILED with error %s\n", ++ unix_username, nt_errstr(status))); ++ goto done; ++ } ++ ++ DEBUG(5, ("check_ntlm_password: PAM Account for user [%s] " ++ "succeeded\n", unix_username)); ++ } ++ ++ DEBUG(3, ("Kerberos ticket principal name is [%s]\n", princ_name)); ++ ++ p = strchr_m(princ_name, '@'); ++ if (!p) { ++ DEBUG(3, ("[%s] Doesn't look like a valid principal\n", ++ princ_name)); ++ status = NT_STATUS_LOGON_FAILURE; ++ goto done; ++ } ++ ++ original_user_name = talloc_strndup(tmp_ctx, princ_name, p - princ_name); ++ if (original_user_name == NULL) { ++ status = NT_STATUS_NO_MEMORY; ++ goto done; ++ } ++ ++ status = create_local_token(mem_ctx, ++ server_info, ++ NULL, ++ original_user_name, ++ session_info); ++ if (!NT_STATUS_IS_OK(status)) { ++ DEBUG(10, ("create_local_token failed: %s\n", ++ nt_errstr(status))); ++ goto done; ++ } ++ ++ goto session_info_ready; ++ } ++ ++ /* This is the standalone legacy code path */ ++ ++ if (pac_blob != NULL) { ++#ifdef HAVE_KRB5 + status = kerberos_pac_logon_info(tmp_ctx, *pac_blob, NULL, NULL, + NULL, NULL, 0, &logon_info); + #else +@@ -121,22 +214,6 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + } + } + +- rc = get_remote_hostname(remote_address, +- &rhost, +- tmp_ctx); +- if (rc < 0) { +- status = NT_STATUS_NO_MEMORY; +- goto done; +- } +- if (strequal(rhost, "UNKNOWN")) { +- rhost = tsocket_address_inet_addr_string(remote_address, +- tmp_ctx); +- if (rhost == NULL) { +- status = NT_STATUS_NO_MEMORY; +- goto done; +- } +- } +- + status = get_user_from_kerberos_info(tmp_ctx, rhost, + princ_name, logon_info, + &is_mapped, &is_guest, +@@ -170,6 +247,8 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + goto done; + } + ++session_info_ready: ++ + /* setup the string used by %U */ + set_current_user_info((*session_info)->unix_info->sanitized_username, + (*session_info)->unix_info->unix_name, +@@ -179,7 +258,9 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + lp_load_with_shares(get_dyn_CONFIGFILE()); + + DEBUG(5, (__location__ "OK: user: %s domain: %s client: %s\n", +- ntuser, ntdomain, rhost)); ++ (*session_info)->info->account_name, ++ (*session_info)->info->domain_name, ++ rhost)); + + status = NT_STATUS_OK; + +-- +2.23.0 + diff --git a/backport-0024-CVE-2020-25717-s3-auth-let-auth3_generate_session_in.patch b/backport-0024-CVE-2020-25717-s3-auth-let-auth3_generate_session_in.patch new file mode 100644 index 0000000..ff3c5e5 --- /dev/null +++ b/backport-0024-CVE-2020-25717-s3-auth-let-auth3_generate_session_in.patch @@ -0,0 +1,85 @@ +From 9f807fdd8d1a148891d389820c329f44f9ffe965 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Tue, 5 Oct 2021 18:12:49 +0200 +Subject: [PATCH 130/266] CVE-2020-25717: s3:auth: let + auth3_generate_session_info_pac() reject a PAC in standalone mode + +We should be strict in standalone mode, that we only support MIT realms +without a PAC in order to keep the code sane. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14556 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Andrew Bartlett +--- + source3/auth/auth_generic.c | 29 +++++++++-------------------- + 1 file changed, 9 insertions(+), 20 deletions(-) + +Conflict:NA +Reference:https://git.samba.org/samba.git/?p=samba.git;a=patch;h=9f807fdd8d1a148891d389820c329f44f9ffe965 + +diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c +index 450c358beeb..7d00cfa95c7 100644 +--- a/source3/auth/auth_generic.c ++++ b/source3/auth/auth_generic.c +@@ -48,8 +48,6 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + { + enum server_role server_role = lp_server_role(); + TALLOC_CTX *tmp_ctx; +- struct PAC_LOGON_INFO *logon_info = NULL; +- struct netr_SamInfo3 *info3_copy = NULL; + bool is_mapped; + bool is_guest; + char *ntuser; +@@ -203,19 +201,20 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + /* This is the standalone legacy code path */ + + if (pac_blob != NULL) { +-#ifdef HAVE_KRB5 +- status = kerberos_pac_logon_info(tmp_ctx, *pac_blob, NULL, NULL, +- NULL, NULL, 0, &logon_info); +-#else +- status = NT_STATUS_ACCESS_DENIED; +-#endif ++ /* ++ * In standalone mode we don't expect a PAC! ++ * we only support MIT realms ++ */ ++ status = NT_STATUS_BAD_TOKEN_TYPE; ++ DBG_WARNING("Unexpected PAC for [%s] in standalone mode - %s\n", ++ princ_name, nt_errstr(status)); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + } + + status = get_user_from_kerberos_info(tmp_ctx, rhost, +- princ_name, logon_info, ++ princ_name, NULL, + &is_mapped, &is_guest, + &ntuser, &ntdomain, + &username, &pw); +@@ -226,19 +225,9 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, + goto done; + } + +- /* Get the info3 from the PAC data if we have it */ +- if (logon_info) { +- status = create_info3_from_pac_logon_info(tmp_ctx, +- logon_info, +- &info3_copy); +- if (!NT_STATUS_IS_OK(status)) { +- goto done; +- } +- } +- + status = make_session_info_krb5(mem_ctx, + ntuser, ntdomain, username, pw, +- info3_copy, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, ++ NULL, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, + session_info); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n", +-- +2.23.0 + diff --git a/backport-winbind-Fix-CID-1456624-Uninitialized-scalar-variabl.patch b/backport-winbind-Fix-CID-1456624-Uninitialized-scalar-variabl.patch new file mode 100644 index 0000000..2e368ee --- /dev/null +++ b/backport-winbind-Fix-CID-1456624-Uninitialized-scalar-variabl.patch @@ -0,0 +1,33 @@ +From 33d4d482718fca10030b5a569f17cb1a2637fc8a Mon Sep 17 00:00:00 2001 +From: Volker Lendecke +Date: Fri, 3 Jan 2020 12:42:03 +0100 +Subject: [PATCH 2619/6935] winbind: Fix CID 1456624 Uninitialized scalar + variable + +Coverity does not get that for (rc!=0) gnutls_error_to_ntstatus() +never returns NT_STATUS_OK + +Signed-off-by: Volker Lendecke +Reviewed-by: Gary Lockyer +Conflict: NA +Reference: https://git.samba.org/?p=samba.git;a=patch;h=33d4d482718fca10030b5a569f17cb1a2637fc8a +--- + source3/winbindd/winbindd_pam.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c +index 1552eb3ce52..a1c6efe6662 100644 +--- a/source3/winbindd/winbindd_pam.c ++++ b/source3/winbindd/winbindd_pam.c +@@ -1738,7 +1738,7 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon( + NTSTATUS result; + uint8_t authoritative = 0; + uint32_t flags = 0; +- uint16_t validation_level; ++ uint16_t validation_level = 0; + union netr_Validation *validation = NULL; + struct netr_SamBaseInfo *base_info = NULL; + bool ok; +-- +2.23.0 + diff --git a/samba.spec b/samba.spec index 3ffbf2e..9c0009e 100644 --- a/samba.spec +++ b/samba.spec @@ -49,7 +49,7 @@ Name: samba Version: 4.11.12 -Release: 6 +Release: 7 Summary: A suite for Linux to interoperate with Windows License: GPLv3+ and LGPLv3+ @@ -80,6 +80,33 @@ Patch10: backport-0002-CVE-2020-14383.patch Patch11: backport-CVE-2020-14318.patch Patch12: backport-CVE-2020-14323.patch +Patch6062: backport-winbind-Fix-CID-1456624-Uninitialized-scalar-variabl.patch + +Patch6157: backport-0001-CVE-2020-25717-winbindd-add-generic-wb_parent_idmap_.patch +Patch6158: backport-0002-CVE-2020-25717-wb_xids2sids-make-use-of-the-new-wb_p.patch +Patch6159: backport-0003-CVE-2020-25717-wb_sids2xids-call-wb_parent_idmap_set.patch +Patch6160: backport-0004-CVE-2020-25717-winbindd-defer-the-setup_child-from-i.patch +Patch6161: backport-0005-CVE-2020-25717-wb_sids2xids-build-state-idmap_doms-b.patch +Patch6162: backport-0006-CVE-2020-25717-winbindd-allow-idmap-backends-to-mark.patch +Patch6163: backport-0007-CVE-2020-25717-s3-idmap_hash-reliable-return-ID_TYPE.patch +Patch6164: backport-0008-CVE-2020-25717-winbindd-call-wb_parent_idmap_setup_s.patch +Patch6165: backport-0009-CVE-2020-25717-winbind-ensure-wb_parent_idmap_setup_.patch +Patch6166: backport-0010-CVE-2020-25717-auth_sam-use-pdb_get_domain_info-to-l.patch +Patch6167: backport-0011-CVE-2020-25717-s3-winbindd-make-sure-we-default-to-r.patch +Patch6168: backport-0012-CVE-2020-25717-s4-auth-ntlm-make-sure-auth_check_pas.patch +Patch6169: backport-0013-CVE-2020-25717-loadparm-Add-new-parameter-min-domain.patch +Patch6170: backport-0014-CVE-2020-25717-s3-auth-Check-minimum-domain-uid.patch +Patch6171: backport-0015-CVE-2020-25717-s3-auth-we-should-not-try-to-autocrea.patch +Patch6172: backport-0016-CVE-2020-25717-s3-auth-no-longer-let-check_account-a.patch +Patch6173: backport-0017-CVE-2020-25717-s3-auth-remove-fallbacks-in-smb_getpw.patch +Patch6174: backport-0018-CVE-2020-25717-s3-auth-don-t-let-create_local_token-.patch +Patch6175: backport-0019-CVE-2020-25719-CVE-2020-25717-auth-gensec-always-req.patch +Patch6176: backport-0020-CVE-2020-25717-s3-ntlm_auth-fix-memory-leaks-in-ntlm.patch +Patch6177: backport-0021-CVE-2020-25717-s3-ntlm_auth-let-ntlm_auth_generate_s.patch +Patch6178: backport-0022-use-set_current_user_info-in-auth3_generate_session_info_p.patch +Patch6179: backport-0023-CVE-2020-25717-s3-auth-let-auth3_generate_session_in.patch +Patch6180: backport-0024-CVE-2020-25717-s3-auth-let-auth3_generate_session_in.patch + BuildRequires: avahi-devel cups-devel dbus-devel docbook-style-xsl e2fsprogs-devel gawk gnupg2 gnutls-devel >= 3.4.7 gpgme-devel BuildRequires: jansson-devel krb5-devel >= %{required_mit_krb5} libacl-devel libaio-devel libarchive-devel libattr-devel BuildRequires: libcap-devel libcmocka-devel libnsl2-devel libtirpc-devel libuuid-devel libxslt lmdb ncurses-devel openldap-devel @@ -3066,6 +3093,12 @@ fi %{_mandir}/man* %changelog +* Thu Nov 25 2021 majun - 4.11.12-7 +- Type:cves +- ID:CVE-2020-25717 +- SUG:NA +- DESC:fix CVE-2020-25717 + * Tue Oct 26 2021 chxssg - 4.11.12-6 - Type:cves - ID:CVE-2020-14318 CVE-2020-14323 CVE-2020-14383 -- Gitee