From 3b655a760bad60a89c4f8de7a80d912642df29d9 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 20 Jan 2021 11:17:22 +0100 Subject: [PATCH 01/10] winbind: move config-reloading code to winbindd_dual.c In preperation of forwarding MSG_SMB_CONF_UPDATED to all childs. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14602 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 81edc65e79aba121db800ec53aadd766e61a0001) --- source3/winbindd/winbindd.c | 23 ++++++----------------- source3/winbindd/winbindd_dual.c | 15 +++++++++++++++ source3/winbindd/winbindd_proto.h | 7 +++++++ 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 57d93f5a769..85b1cc6e651 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -99,7 +99,7 @@ struct imessaging_context *winbind_imessaging_context(void) /* Reload configuration */ -static bool reload_services_file(const char *lfile) +bool winbindd_reload_services_file(const char *lfile) { const struct loadparm_substitution *lp_sub = loadparm_s3_global_substitution(); @@ -153,7 +153,7 @@ static void winbindd_status(void) /* Flush client cache */ -static void flush_caches(void) +void winbindd_flush_caches(void) { /* We need to invalidate cached user list entries on a SIGHUP otherwise cached access denied errors due to restrict anonymous @@ -360,7 +360,7 @@ static void winbindd_sig_hup_handler(struct tevent_context *ev, DEBUG(1,("Reloading services after SIGHUP\n")); flush_caches_noinit(); - reload_services_file(file); + winbindd_reload_services_file(file); } bool winbindd_setup_sig_hup_handler(const char *lfile) @@ -444,18 +444,6 @@ static bool winbindd_setup_sig_usr2_handler(void) return true; } -/* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/ -static void msg_reload_services(struct messaging_context *msg, - void *private_data, - uint32_t msg_type, - struct server_id server_id, - DATA_BLOB *data) -{ - /* Flush various caches */ - flush_caches(); - reload_services_file((const char *) private_data); -} - /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/ static void msg_shutdown(struct messaging_context *msg, void *private_data, @@ -1417,7 +1405,8 @@ static void winbindd_register_handlers(struct messaging_context *msg_ctx, /* React on 'smbcontrol winbindd reload-config' in the same way as to SIGHUP signal */ messaging_register(msg_ctx, NULL, - MSG_SMB_CONF_UPDATED, msg_reload_services); + MSG_SMB_CONF_UPDATED, + winbindd_msg_reload_services_parent); messaging_register(msg_ctx, NULL, MSG_SHUTDOWN, msg_shutdown); @@ -1806,7 +1795,7 @@ int main(int argc, const char **argv) exit(1); } - if (!reload_services_file(NULL)) { + if (!winbindd_reload_services_file(NULL)) { DEBUG(0, ("error opening config file\n")); exit(1); } diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 73715b4b57d..56b3dac6dec 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -927,6 +927,21 @@ void winbind_disconnect_dc_parent(struct messaging_context *msg_ctx, forall_children(winbind_msg_relay_fn, &state); } +/* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/ +void winbindd_msg_reload_services_parent(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + DBG_DEBUG("Got reload-config message\n"); + + /* Flush various caches */ + winbindd_flush_caches(); + + winbindd_reload_services_file((const char *)private_data); +} + /* Set our domains as offline and forward the offline message to our children. */ struct winbind_msg_on_offline_state { diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 2a829b0171a..6d4ffa726f1 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -31,6 +31,8 @@ bool winbindd_setup_sig_hup_handler(const char *lfile); bool winbindd_use_idmap_cache(void); bool winbindd_use_cache(void); char *get_winbind_priv_pipe_dir(void); +void winbindd_flush_caches(void); +bool winbindd_reload_services_file(const char *lfile); /* The following definitions come from winbindd/winbindd_ads.c */ @@ -341,6 +343,11 @@ void winbind_msg_ip_dropped_parent(struct messaging_context *msg_ctx, uint32_t msg_type, struct server_id server_id, DATA_BLOB *data); +void winbindd_msg_reload_services_parent(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data); NTSTATUS winbindd_reinit_after_fork(const struct winbindd_child *myself, const char *logfilename); struct winbindd_domain *wb_child_domain(void); -- 2.26.2 From 37fb65bb202c5435df84a2e13f74e662c4e4b484 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 20 Jan 2021 12:27:23 +0100 Subject: [PATCH 02/10] winbind: set logfile after reloading config lp_load_global() will overwrite whatever we've set with lp_set_logfile(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14602 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 0c4497f8c66d0ea7c68d42c19e859932ebc3e2ac) --- source3/winbindd/winbindd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 85b1cc6e651..44790ea3429 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -114,15 +114,15 @@ bool winbindd_reload_services_file(const char *lfile) TALLOC_FREE(fname); } + reopen_logs(); + ret = lp_load_global(get_dyn_CONFIGFILE()); + /* if this is a child, restore the logfile to the special name - , idmap, etc. */ if (lfile && *lfile) { lp_set_logfile(lfile); } - reopen_logs(); - ret = lp_load_global(get_dyn_CONFIGFILE()); - reopen_logs(); load_interfaces(); winbindd_setup_max_fds(); -- 2.26.2 From f2bb3ea9ee35c9aa4baf91f0cd79b2aff40ace66 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Wed, 20 Jan 2021 12:00:16 +0100 Subject: [PATCH 03/10] winbind: handle MSG_SMB_CONF_UPDATED in the winbinds children BUG: https://bugzilla.samba.org/show_bug.cgi?id=14602 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 072ef48001710ed8326c83295f2d3cc301d27cfe) --- source3/winbindd/winbindd_dual.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 56b3dac6dec..9f14dfdb4f1 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -927,6 +927,16 @@ void winbind_disconnect_dc_parent(struct messaging_context *msg_ctx, forall_children(winbind_msg_relay_fn, &state); } +static void winbindd_msg_reload_services_child(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + DBG_DEBUG("Got reload-config message\n"); + winbindd_reload_services_file((const char *)private_data); +} + /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/ void winbindd_msg_reload_services_parent(struct messaging_context *msg, void *private_data, @@ -934,12 +944,20 @@ void winbindd_msg_reload_services_parent(struct messaging_context *msg, struct server_id server_id, DATA_BLOB *data) { + struct winbind_msg_relay_state state = { + .msg_ctx = msg, + .msg_type = msg_type, + .data = data, + }; + DBG_DEBUG("Got reload-config message\n"); /* Flush various caches */ winbindd_flush_caches(); winbindd_reload_services_file((const char *)private_data); + + forall_children(winbind_msg_relay_fn, &state); } /* Set our domains as offline and forward the offline message to our children. */ @@ -1774,6 +1792,10 @@ static bool fork_domain_child(struct winbindd_child *child) messaging_register(global_messaging_context(), NULL, MSG_WINBIND_DISCONNECT_DC, winbind_msg_disconnect_dc); + messaging_register(global_messaging_context(), + override_logfile ? NULL : child->logfilename, + MSG_SMB_CONF_UPDATED, + winbindd_msg_reload_services_child); primary_domain = find_our_domain(); -- 2.26.2 From 6ec3ece4d66999961d510a93dc8f4c95e1305fb5 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 11 Jan 2021 16:15:15 +0100 Subject: [PATCH 04/10] winbind: move "winbind:ignore domain" logic to a seperate function BUG: https://bugzilla.samba.org/show_bug.cgi?id=14602 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 894caca79476d25a0268d89b2ad8a5758b7e31f3) --- source3/include/proto.h | 1 + source3/lib/util_names.c | 20 ++++++++++++++++++++ source3/winbindd/winbindd_util.c | 10 ++-------- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 5d5da28bbb5..921b92830c2 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -319,6 +319,7 @@ struct passwd *Get_Pwnam_alloc(TALLOC_CTX *mem_ctx, const char *user); /* The following definitions come from lib/util_names.c */ const char *get_global_sam_name(void); const char *my_sam_name(void); +bool is_allowed_domain(const char *domain_name); /* The following definitions come from lib/util.c */ diff --git a/source3/lib/util_names.c b/source3/lib/util_names.c index dc5c530346c..efef88f4f7b 100644 --- a/source3/lib/util_names.c +++ b/source3/lib/util_names.c @@ -185,3 +185,23 @@ const char *my_sam_name(void) return lp_workgroup(); } + +bool is_allowed_domain(const char *domain_name) +{ + const char **ignored_domains = NULL; + const char **dom = NULL; + + ignored_domains = lp_parm_string_list(-1, + "winbind", + "ignore domains", + NULL); + + for (dom = ignored_domains; dom != NULL && *dom != NULL; dom++) { + if (gen_fnmatch(*dom, domain_name) == 0) { + DBG_NOTICE("Ignoring domain '%s'\n", domain_name); + return false; + } + } + + return true; +} diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index c2f02b74211..bec706f87de 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -123,8 +123,6 @@ static NTSTATUS add_trusted_domain(const char *domain_name, struct winbindd_domain **_d) { struct winbindd_domain *domain = NULL; - const char **ignored_domains = NULL; - const char **dom = NULL; int role = lp_server_role(); struct dom_sid_buf buf; @@ -133,12 +131,8 @@ static NTSTATUS add_trusted_domain(const char *domain_name, return NT_STATUS_INVALID_PARAMETER; } - ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL); - for (dom=ignored_domains; dom && *dom; dom++) { - if (gen_fnmatch(*dom, domain_name) == 0) { - DEBUG(2,("Ignoring domain '%s'\n", domain_name)); - return NT_STATUS_NO_SUCH_DOMAIN; - } + if (!is_allowed_domain(domain_name)) { + return NT_STATUS_NO_SUCH_DOMAIN; } /* -- 2.26.2 From c9205cb56aeaa6285c7b6c2bf9b764ae1d26f11b Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 11 Jan 2021 16:50:31 +0100 Subject: [PATCH 05/10] winbind: check for allowed domains in winbindd_dual_pam_auth() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14602 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 4cefdf03fec91cdcf700922b1a5ceca02407e259) --- source3/winbindd/winbindd_pam.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index a3d8716f781..79dc736ca0b 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -2404,6 +2404,15 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, goto done; } + if (!is_allowed_domain(info3->base.logon_domain.string)) { + DBG_NOTICE("Authentication failed for user [%s] " + "from firewalled domain [%s]\n", + info3->base.account_name.string, + info3->base.logon_domain.string); + result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; + goto done; + } + result = append_auth_data(state->mem_ctx, state->response, state->request->flags, validation_level, -- 2.26.2 From 41c7d8738e1cd08241feb8dc3402472b10e852e8 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 11 Jan 2021 17:10:19 +0100 Subject: [PATCH 06/10] winbind: check for allowed domains in winbindd_dual_pam_auth_crap() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14602 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (backported from commit c17bc9c6115e4e92132f3cb912547eac78227938) [slow@samba.org: removed knownfail entry] --- source3/winbindd/winbindd_pam.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 79dc736ca0b..78565d2854f 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -2766,6 +2766,16 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } + if (!is_allowed_domain(info3->base.logon_domain.string)) { + DBG_NOTICE("Authentication failed for user [%s] " + "from firewalled domain [%s]\n", + info3->base.account_name.string, + info3->base.logon_domain.string); + state->response->data.auth.authoritative = true; + result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; + goto done; + } + result = append_auth_data(state->mem_ctx, state->response, state->request->flags, validation_level, -- 2.26.2 From 51e07a58d1eb25cd1745ac38c5476605fb1e166b Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 11 Jan 2021 17:19:05 +0100 Subject: [PATCH 07/10] winbind: check for allowed domains in winbindd_dual_pam_chng_pswd_auth_crap() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14602 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 4bc17600bc50fbc0e54d9d019d8db67001fc3eef) --- source3/winbindd/winbindd_pam.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 78565d2854f..477d52da3ed 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -3105,6 +3105,15 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai fstrcpy(domain,lp_workgroup()); } + if (!is_allowed_domain(domain)) { + DBG_NOTICE("Authentication failed for user [%s] " + "from firewalled domain [%s]\n", + state->request->data.chng_pswd_auth_crap.user, + domain); + result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; + goto done; + } + if(!*user) { fstrcpy(user, state->request->data.chng_pswd_auth_crap.user); } -- 2.26.2 From 0c5ffbe8c5492f0cb394b1a07afc45f25dcd7bce Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 11 Jan 2021 17:59:48 +0100 Subject: [PATCH 08/10] winbind: check for allowed domains in winbindd_dual_pam_chauthtok() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14602 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit 88e92faace7ec17810903166fa3433aa4842a4e3) --- source3/winbindd/winbindd_pam.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 477d52da3ed..d7cbcffa6b9 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -2844,6 +2844,14 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact goto done; } + if (!is_allowed_domain(domain)) { + DBG_NOTICE("Authentication failed for user [%s] " + "from firewalled domain [%s]\n", + user, domain); + result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; + goto done; + } + /* Change password */ oldpass = state->request->data.chauthtok.oldpass; -- 2.26.2 From adee7795649409a1c746aac8b1e68541ee63ec6c Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 14 Jan 2021 10:42:53 +0100 Subject: [PATCH 09/10] winbind: check for allowed domains in winbindd_pam_auth_pac_verify() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14602 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit da474ddd13d84f07f5da81c843e651844f33a003) --- source3/winbindd/winbindd_pam.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index d7cbcffa6b9..94416498be7 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -3324,6 +3324,14 @@ NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state, return result; } + if (!is_allowed_domain(info6->base.logon_domain.string)) { + DBG_NOTICE("Authentication failed for user [%s] " + "from firewalled domain [%s]\n", + info6->base.account_name.string, + info6->base.logon_domain.string); + return NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; + } + result = map_info6_to_validation(state->mem_ctx, info6, &validation_level, -- 2.26.2 From fa411e8a93da02e87cfd7b5d6aa4b424eef36983 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 15 Jan 2021 12:56:25 +0100 Subject: [PATCH 10/10] s3/auth: implement "winbind:ignore domains" Under the following conditions a user from an ignored domain might be able to authenticate: - using Kerberos - successfully previous authentication so the idmap and name caches are filled - winbind not running (fwiw, winbindd is mandatory on a domain member) - nscd running with a cached getpwnam for the ignored user (otherwise auth fails because getpwnam fails) - lookup_name() function being modified to look into the name cache before contacting winbindd. Currently it talks directly to winbindd and that will check the cache. Currently, authentication will only fail because creating the local token for the user fails because an LSA lookupname RPC call fails (because winbindd is not running). All of this makes a successfull authentication unlikelly, but that is more by accident then by design. To ensures that if winbindd is not running and as such winbindd itself can not enforce the restriction, also implement the ignored domains check in the auth system as a last line of defense. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14602 RN: "winbind:ignore domains" doesn't prevent user login from trusted domain Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (cherry picked from commit df5fe2d835169161d3930acf1e9c750dd2bc64b6) --- source3/auth/auth_util.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 3e0fcea2410..39713df539f 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -486,6 +486,14 @@ NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, return NT_STATUS_LOGON_FAILURE; } + if (!is_allowed_domain(server_info->info3->base.logon_domain.string)) { + DBG_NOTICE("Authentication failed for user [%s] " + "from firewalled domain [%s]\n", + server_info->info3->base.account_name.string, + server_info->info3->base.logon_domain.string); + return NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; + } + if (server_info->cached_session_info != NULL) { session_info = copy_session_info(mem_ctx, server_info->cached_session_info); -- 2.26.2