From 0c6aabcc81e2b5fc09e69d2718f0e51a282b3420 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 6 Dec 2022 16:00:36 +0100 Subject: [PATCH 01/30] CVE-2022-38023 docs-xml: improve wording for several options: "takes precedence" -> "overrides" BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 8ec62694a94c346e6ba8f3144a417c9984a1c8b9) --- docs-xml/smbdotconf/logon/rejectmd5clients.xml | 2 +- docs-xml/smbdotconf/security/serverschannel.xml | 2 +- docs-xml/smbdotconf/winbind/rejectmd5servers.xml | 2 +- docs-xml/smbdotconf/winbind/requirestrongkey.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs-xml/smbdotconf/logon/rejectmd5clients.xml b/docs-xml/smbdotconf/logon/rejectmd5clients.xml index 41684ef10805..0bb9f6f6c8ec 100644 --- a/docs-xml/smbdotconf/logon/rejectmd5clients.xml +++ b/docs-xml/smbdotconf/logon/rejectmd5clients.xml @@ -10,7 +10,7 @@ You can set this to yes if all domain members support aes. This will prevent downgrade attacks. - This option takes precedence to the 'allow nt4 crypto' option. + This option overrides the 'allow nt4 crypto' option. no diff --git a/docs-xml/smbdotconf/security/serverschannel.xml b/docs-xml/smbdotconf/security/serverschannel.xml index cd2543113f3e..bd9fea84a7e7 100644 --- a/docs-xml/smbdotconf/security/serverschannel.xml +++ b/docs-xml/smbdotconf/security/serverschannel.xml @@ -59,7 +59,7 @@ See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497 - This option takes precedence to the option. + This option overrides the option. server require schannel:LEGACYCOMPUTER1$ = no diff --git a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml index 37656293aa47..151b4676c57b 100644 --- a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml +++ b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml @@ -15,7 +15,7 @@ The behavior can be controlled per netbios domain by using 'reject md5 servers:NETBIOSDOMAIN = yes' as option. - This option takes precedence to the option. + This option overrides the option. no diff --git a/docs-xml/smbdotconf/winbind/requirestrongkey.xml b/docs-xml/smbdotconf/winbind/requirestrongkey.xml index 4db62bfb02db..b17620ec8f1d 100644 --- a/docs-xml/smbdotconf/winbind/requirestrongkey.xml +++ b/docs-xml/smbdotconf/winbind/requirestrongkey.xml @@ -19,7 +19,7 @@ This option yields precedence to the option. - This option takes precedence to the option. + This option overrides the option. yes -- 2.34.1 From 99c61592d4c2d2dbdf50765b085ece40c2b3099c Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 6 Dec 2022 16:05:26 +0100 Subject: [PATCH 02/30] CVE-2022-38023 docs-xml: improve wording for several options: "yields precedence" -> "is over-riden" BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 830e865ba5648f6520bc552ffd71b61f754b8251) --- docs-xml/smbdotconf/logon/allownt4crypto.xml | 2 +- docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml | 2 +- docs-xml/smbdotconf/security/clientschannel.xml | 2 +- docs-xml/smbdotconf/security/serverschannel.xml | 2 +- docs-xml/smbdotconf/winbind/requirestrongkey.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs-xml/smbdotconf/logon/allownt4crypto.xml b/docs-xml/smbdotconf/logon/allownt4crypto.xml index 03dc8fa93f72..06afcef73b1b 100644 --- a/docs-xml/smbdotconf/logon/allownt4crypto.xml +++ b/docs-xml/smbdotconf/logon/allownt4crypto.xml @@ -18,7 +18,7 @@ "allow nt4 crypto = yes" allows weak crypto to be negotiated, maybe via downgrade attacks. - This option yields precedence to the 'reject md5 clients' option. + This option is over-ridden by the 'reject md5 clients' option. no diff --git a/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml b/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml index 03531adbfb36..8bccab391cc2 100644 --- a/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml +++ b/docs-xml/smbdotconf/security/allowdcerpcauthlevelconnect.xml @@ -15,7 +15,7 @@ The behavior can be overwritten per interface name (e.g. lsarpc, netlogon, samr, srvsvc, winreg, wkssvc ...) by using 'allow dcerpc auth level connect:interface = yes' as option. - This option yields precedence to the implementation specific restrictions. + This option is over-ridden by the implementation specific restrictions. E.g. the drsuapi and backupkey protocols require DCERPC_AUTH_LEVEL_PRIVACY. The dnsserver protocol requires DCERPC_AUTH_LEVEL_INTEGRITY. diff --git a/docs-xml/smbdotconf/security/clientschannel.xml b/docs-xml/smbdotconf/security/clientschannel.xml index 5b07da95050c..d124ad481818 100644 --- a/docs-xml/smbdotconf/security/clientschannel.xml +++ b/docs-xml/smbdotconf/security/clientschannel.xml @@ -23,7 +23,7 @@ Note that for active directory domains this is hardcoded to yes. - This option yields precedence to the option. + This option is over-ridden by the option. yes auto diff --git a/docs-xml/smbdotconf/security/serverschannel.xml b/docs-xml/smbdotconf/security/serverschannel.xml index bd9fea84a7e7..394ffdc36fbd 100644 --- a/docs-xml/smbdotconf/security/serverschannel.xml +++ b/docs-xml/smbdotconf/security/serverschannel.xml @@ -23,7 +23,7 @@ If you still have legacy domain members use the option. - This option yields precedence to the option. + This option is over-ridden by the option. diff --git a/docs-xml/smbdotconf/winbind/requirestrongkey.xml b/docs-xml/smbdotconf/winbind/requirestrongkey.xml index b17620ec8f1d..9c1c1d7af148 100644 --- a/docs-xml/smbdotconf/winbind/requirestrongkey.xml +++ b/docs-xml/smbdotconf/winbind/requirestrongkey.xml @@ -17,7 +17,7 @@ Note for active directory domain this option is hardcoded to 'yes' - This option yields precedence to the option. + This option is over-ridden by the option. This option overrides the option. -- 2.34.1 From 7a08094b4532fb17161dc4c8d50425226becd528 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Nov 2022 14:46:59 +0100 Subject: [PATCH 03/30] CVE-2022-38023 libcli/auth: pass lp_ctx to netlogon_creds_cli_set_global_db() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 992f39a2c8a58301ceeb965f401e29cd64c5a209) --- libcli/auth/netlogon_creds_cli.c | 3 ++- libcli/auth/netlogon_creds_cli.h | 2 +- source3/rpc_client/cli_netlogon.c | 2 +- source3/utils/destroy_netlogon_creds_cli.c | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 716a565128dd..a31de47551d5 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -202,7 +202,8 @@ static NTSTATUS netlogon_creds_cli_context_common( static struct db_context *netlogon_creds_cli_global_db; -NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db) +NTSTATUS netlogon_creds_cli_set_global_db(struct loadparm_context *lp_ctx, + struct db_context **db) { if (netlogon_creds_cli_global_db != NULL) { return NT_STATUS_INVALID_PARAMETER_MIX; diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h index 6f40a46aa0a6..d10197c2d2af 100644 --- a/libcli/auth/netlogon_creds_cli.h +++ b/libcli/auth/netlogon_creds_cli.h @@ -31,7 +31,7 @@ struct messaging_context; struct dcerpc_binding_handle; struct db_context; -NTSTATUS netlogon_creds_cli_set_global_db(struct db_context **db); +NTSTATUS netlogon_creds_cli_set_global_db(struct loadparm_context *lp_ctx, struct db_context **db); NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx); void netlogon_creds_cli_close_global_db(void); diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index da445122dbdc..762802d32780 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -76,7 +76,7 @@ NTSTATUS rpccli_pre_open_netlogon_creds(void) return NT_STATUS_NO_MEMORY; } - status = netlogon_creds_cli_set_global_db(&global_db); + status = netlogon_creds_cli_set_global_db(lp_ctx, &global_db); TALLOC_FREE(frame); if (!NT_STATUS_IS_OK(status)) { return status; diff --git a/source3/utils/destroy_netlogon_creds_cli.c b/source3/utils/destroy_netlogon_creds_cli.c index f28cad527dfb..a2e1952e434c 100644 --- a/source3/utils/destroy_netlogon_creds_cli.c +++ b/source3/utils/destroy_netlogon_creds_cli.c @@ -82,7 +82,7 @@ int main(int argc, const char *argv[]) goto done; } - status = netlogon_creds_cli_set_global_db(&global_db); + status = netlogon_creds_cli_set_global_db(lp_ctx, &global_db); if (!NT_STATUS_IS_OK(status)) { fprintf(stderr, "netlogon_creds_cli_set_global_db failed: %s\n", -- 2.34.1 From 5e3c1871c3c0869b1cf95ed9311df03e41a12f05 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Nov 2022 14:47:33 +0100 Subject: [PATCH 04/30] CVE-2022-38023 libcli/auth: add/use netlogon_creds_cli_warn_options() This warns the admin about insecure options BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 7e7adf86e59e8a673fbe87de46cef0d62221e800) --- libcli/auth/netlogon_creds_cli.c | 66 ++++++++++++++++++++++++++++++++ libcli/auth/netlogon_creds_cli.h | 2 + 2 files changed, 68 insertions(+) diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index a31de47551d5..848d993a3c66 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -205,6 +205,8 @@ static struct db_context *netlogon_creds_cli_global_db; NTSTATUS netlogon_creds_cli_set_global_db(struct loadparm_context *lp_ctx, struct db_context **db) { + netlogon_creds_cli_warn_options(lp_ctx); + if (netlogon_creds_cli_global_db != NULL) { return NT_STATUS_INVALID_PARAMETER_MIX; } @@ -219,6 +221,8 @@ NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx) struct db_context *global_db; int hash_size, tdb_flags; + netlogon_creds_cli_warn_options(lp_ctx); + if (netlogon_creds_cli_global_db != NULL) { return NT_STATUS_OK; } @@ -259,6 +263,68 @@ void netlogon_creds_cli_close_global_db(void) TALLOC_FREE(netlogon_creds_cli_global_db); } +void netlogon_creds_cli_warn_options(struct loadparm_context *lp_ctx) +{ + bool global_reject_md5_servers = lpcfg_reject_md5_servers(lp_ctx); + bool global_require_strong_key = lpcfg_require_strong_key(lp_ctx); + int global_client_schannel = lpcfg_client_schannel(lp_ctx); + bool global_seal_secure_channel = lpcfg_winbind_sealed_pipes(lp_ctx); + static bool warned_global_reject_md5_servers = false; + static bool warned_global_require_strong_key = false; + static bool warned_global_client_schannel = false; + static bool warned_global_seal_secure_channel = false; + static int warned_global_pid = 0; + int current_pid = tevent_cached_getpid(); + + if (warned_global_pid != current_pid) { + warned_global_reject_md5_servers = false; + warned_global_require_strong_key = false; + warned_global_client_schannel = false; + warned_global_seal_secure_channel = false; + warned_global_pid = current_pid; + } + + if (!global_reject_md5_servers && !warned_global_reject_md5_servers) { + /* + * We want admins to notice their misconfiguration! + */ + DBG_ERR("CVE-2022-38023 (and others): " + "Please configure 'reject md5 servers = yes' (the default), " + "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); + warned_global_reject_md5_servers = true; + } + + if (!global_require_strong_key && !warned_global_require_strong_key) { + /* + * We want admins to notice their misconfiguration! + */ + DBG_ERR("CVE-2022-38023 (and others): " + "Please configure 'require strong key = yes' (the default), " + "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); + warned_global_require_strong_key = true; + } + + if (global_client_schannel != true && !warned_global_client_schannel) { + /* + * We want admins to notice their misconfiguration! + */ + DBG_ERR("CVE-2022-38023 (and others): " + "Please configure 'client schannel = yes' (the default), " + "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); + warned_global_client_schannel = true; + } + + if (!global_seal_secure_channel && !warned_global_seal_secure_channel) { + /* + * We want admins to notice their misconfiguration! + */ + DBG_ERR("CVE-2022-38023 (and others): " + "Please configure 'winbind sealed pipes = yes' (the default), " + "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); + warned_global_seal_secure_channel = true; + } +} + NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, struct messaging_context *msg_ctx, const char *client_account, diff --git a/libcli/auth/netlogon_creds_cli.h b/libcli/auth/netlogon_creds_cli.h index d10197c2d2af..600242e1aea7 100644 --- a/libcli/auth/netlogon_creds_cli.h +++ b/libcli/auth/netlogon_creds_cli.h @@ -35,6 +35,8 @@ NTSTATUS netlogon_creds_cli_set_global_db(struct loadparm_context *lp_ctx, struc NTSTATUS netlogon_creds_cli_open_global_db(struct loadparm_context *lp_ctx); void netlogon_creds_cli_close_global_db(void); +void netlogon_creds_cli_warn_options(struct loadparm_context *lp_ctx); + NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, struct messaging_context *msg_ctx, const char *client_account, -- 2.34.1 From e741d4967b5b4ff3ec7eb558bc3d1668fde9fe35 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Nov 2022 16:16:05 +0100 Subject: [PATCH 05/30] CVE-2022-38023 s3:net: add and use net_warn_member_options() helper This makes sure domain member related 'net' commands print warnings about unsecure smb.conf options. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 1fdf1d55a5dd550bdb16d037b5dc995c33c1a67a) --- source3/utils/net.c | 6 ++++++ source3/utils/net_ads.c | 14 ++++++++++++++ source3/utils/net_dom.c | 2 ++ source3/utils/net_join.c | 2 ++ source3/utils/net_offlinejoin.c | 2 ++ source3/utils/net_proto.h | 2 ++ source3/utils/net_rpc.c | 10 ++++++++++ source3/utils/net_util.c | 14 ++++++++++++++ 8 files changed, 52 insertions(+) diff --git a/source3/utils/net.c b/source3/utils/net.c index e1e14743c117..b96d7f5d9d48 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -85,6 +85,8 @@ enum netr_SchannelType get_sec_channel_type(const char *param) static int net_changetrustpw(struct net_context *c, int argc, const char **argv) { + net_warn_member_options(); + if (net_ads_check_our_domain(c) == 0) return net_ads_changetrustpw(c, argc, argv); @@ -112,6 +114,8 @@ static int net_primarytrust_dumpinfo(struct net_context *c, int argc, return 1; } + net_warn_member_options(); + if (c->opt_stdin) { set_line_buffering(stdin); set_line_buffering(stdout); @@ -193,6 +197,8 @@ static int net_changesecretpw(struct net_context *c, int argc, return 1; } + net_warn_member_options(); + if(c->opt_force) { struct secrets_domain_info1 *info = NULL; struct secrets_domain_info1_change *prev = NULL; diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 9b2cc50aa31f..7859225a03b7 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -1414,6 +1414,8 @@ static int net_ads_status(struct net_context *c, int argc, const char **argv) return -1; } + net_warn_member_options(); + status = ads_startup(c, true, tmp_ctx, &ads); if (!ADS_ERR_OK(status)) { goto out; @@ -1556,6 +1558,8 @@ static ADS_STATUS net_ads_join_ok(struct net_context *c) return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED); } + net_warn_member_options(); + net_use_krb_machine_account(c); get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip); @@ -1588,6 +1592,8 @@ int net_ads_testjoin(struct net_context *c, int argc, const char **argv) return -1; } + net_warn_member_options(); + /* Display success or failure */ status = net_ads_join_ok(c); if (!ADS_ERR_OK(status)) { @@ -1685,6 +1691,8 @@ int net_ads_join(struct net_context *c, int argc, const char **argv) return net_ads_join_usage(c, argc, argv); } + net_warn_member_options(); + if (!modify_config) { werr = check_ads_config(); if (!W_ERROR_IS_OK(werr)) { @@ -2659,6 +2667,8 @@ int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv) goto out; } + net_warn_member_options(); + net_use_krb_machine_account(c); use_in_memory_ccache(); @@ -2961,6 +2971,8 @@ static int net_ads_keytab_add(struct net_context *c, return -1; } + net_warn_member_options(); + d_printf(_("Processing principals to add...\n")); if (!c->opt_user_specified && c->opt_password == NULL) { @@ -3011,6 +3023,8 @@ static int net_ads_keytab_create(struct net_context *c, int argc, const char **a return -1; } + net_warn_member_options(); + if (!c->opt_user_specified && c->opt_password == NULL) { net_use_krb_machine_account(c); } diff --git a/source3/utils/net_dom.c b/source3/utils/net_dom.c index 13e65a933142..4b48e1566bc8 100644 --- a/source3/utils/net_dom.c +++ b/source3/utils/net_dom.c @@ -154,6 +154,8 @@ static int net_dom_join(struct net_context *c, int argc, const char **argv) return net_dom_usage(c, argc, argv); } + net_warn_member_options(); + if (c->opt_host) { server_name = c->opt_host; } diff --git a/source3/utils/net_join.c b/source3/utils/net_join.c index 1493dff74d7b..f67f08f79a81 100644 --- a/source3/utils/net_join.c +++ b/source3/utils/net_join.c @@ -39,6 +39,8 @@ int net_join(struct net_context *c, int argc, const char **argv) return 0; } + net_warn_member_options(); + if (net_ads_check_our_domain(c) == 0) { if (net_ads_join(c, argc, argv) == 0) return 0; diff --git a/source3/utils/net_offlinejoin.c b/source3/utils/net_offlinejoin.c index 03e5df0eace9..0cfd5fdfe235 100644 --- a/source3/utils/net_offlinejoin.c +++ b/source3/utils/net_offlinejoin.c @@ -49,6 +49,8 @@ int net_offlinejoin(struct net_context *c, int argc, const char **argv) return -1; } + net_warn_member_options(); + status = libnetapi_net_init(&c->netapi_ctx); if (status != 0) { return -1; diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h index 1cc8fdf35afe..fe6b5dd9b84f 100644 --- a/source3/utils/net_proto.h +++ b/source3/utils/net_proto.h @@ -448,6 +448,8 @@ int net_run_function(struct net_context *c, int argc, const char **argv, const char *whoami, struct functable *table); void net_display_usage_from_functable(struct functable *table); +void net_warn_member_options(void); + const char *net_share_type_str(int num_type); NTSTATUS net_scan_dc(struct net_context *c, diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 97c0158d612f..16a541413d2e 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -371,6 +371,8 @@ static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv) return 0; } + net_warn_member_options(); + mem_ctx = talloc_init("net_rpc_oldjoin"); if (!mem_ctx) { return -1; @@ -490,6 +492,8 @@ int net_rpc_testjoin(struct net_context *c, int argc, const char **argv) return 0; } + net_warn_member_options(); + mem_ctx = talloc_init("net_rpc_testjoin"); if (!mem_ctx) { return -1; @@ -564,6 +568,8 @@ static int net_rpc_join_newstyle(struct net_context *c, int argc, const char **a return 0; } + net_warn_member_options(); + mem_ctx = talloc_init("net_rpc_join_newstyle"); if (!mem_ctx) { return -1; @@ -685,6 +691,8 @@ int net_rpc_join(struct net_context *c, int argc, const char **argv) return -1; } + net_warn_member_options(); + if (strlen(lp_netbios_name()) > 15) { d_printf(_("Our netbios name can be at most 15 chars long, " "\"%s\" is %u chars long\n"), @@ -815,6 +823,8 @@ int net_rpc_info(struct net_context *c, int argc, const char **argv) return 0; } + net_warn_member_options(); + return run_rpc_command(c, NULL, &ndr_table_samr, NET_FLAGS_PDC, rpc_info_internals, argc, argv); diff --git a/source3/utils/net_util.c b/source3/utils/net_util.c index 298d9a64dc0c..f3b7755063bf 100644 --- a/source3/utils/net_util.c +++ b/source3/utils/net_util.c @@ -31,6 +31,7 @@ #include "libsmb/libsmb.h" #include "lib/param/param.h" #include "auth/gensec/gensec.h" +#include "libcli/auth/netlogon_creds_cli.h" #include "lib/cmdline/cmdline.h" NTSTATUS net_rpc_lookup_name(struct net_context *c, @@ -478,6 +479,19 @@ void net_display_usage_from_functable(struct functable *table) } } +void net_warn_member_options(void) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct loadparm_context *lp_ctx = NULL; + + lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); + if (lp_ctx != NULL) { + netlogon_creds_cli_warn_options(lp_ctx); + } + + TALLOC_FREE(frame); +} + const char *net_share_type_str(int num_type) { switch(num_type) { -- 2.34.1 From 9fcde82de834cc8f9915c493911343775811b24c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Nov 2022 14:59:36 +0100 Subject: [PATCH 06/30] CVE-2022-38023 s3:winbindd: also allow per domain "winbind sealed pipes:DOMAIN" and "require strong key:DOMAIN" This avoids advising insecure defaults for the global options. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit d60828f6391307a59abaa02b72b6a8acf66b2fef) --- source3/winbindd/winbindd_cm.c | 41 +++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index 28316e10d72d..e774bf90511f 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -2457,6 +2457,8 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, bool retry = false; /* allow one retry attempt for expired session */ const char *remote_name = NULL; const struct sockaddr_storage *remote_sockaddr = NULL; + bool sealed_pipes = true; + bool strong_key = true; if (sid_check_is_our_sam(&domain->sid)) { if (domain->rodc == false || need_rw_dc == false) { @@ -2636,14 +2638,24 @@ retry: anonymous: + sealed_pipes = lp_winbind_sealed_pipes(); + sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes", + domain->name, + sealed_pipes); + strong_key = lp_require_strong_key(); + strong_key = lp_parm_bool(-1, "require strong key", + domain->name, + strong_key); + /* Finally fall back to anonymous. */ - if (lp_winbind_sealed_pipes() || lp_require_strong_key()) { + if (sealed_pipes || strong_key) { status = NT_STATUS_DOWNGRADE_DETECTED; DEBUG(1, ("Unwilling to make SAMR connection to domain %s " "without connection level security, " - "must set 'winbind sealed pipes = false' and " - "'require strong key = false' to proceed: %s\n", - domain->name, nt_errstr(status))); + "must set 'winbind sealed pipes:%s = false' and " + "'require strong key:%s = false' to proceed: %s\n", + domain->name, domain->name, domain->name, + nt_errstr(status))); goto done; } status = cli_rpc_pipe_open_noauth(conn->cli, &ndr_table_samr, @@ -2800,6 +2812,8 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, bool retry = false; /* allow one retry attempt for expired session */ const char *remote_name = NULL; const struct sockaddr_storage *remote_sockaddr = NULL; + bool sealed_pipes = true; + bool strong_key = true; retry: result = init_dc_connection_rpc(domain, false); @@ -2961,13 +2975,24 @@ retry: goto done; } - if (lp_winbind_sealed_pipes() || lp_require_strong_key()) { + sealed_pipes = lp_winbind_sealed_pipes(); + sealed_pipes = lp_parm_bool(-1, "winbind sealed pipes", + domain->name, + sealed_pipes); + strong_key = lp_require_strong_key(); + strong_key = lp_parm_bool(-1, "require strong key", + domain->name, + strong_key); + + /* Finally fall back to anonymous. */ + if (sealed_pipes || strong_key) { result = NT_STATUS_DOWNGRADE_DETECTED; DEBUG(1, ("Unwilling to make LSA connection to domain %s " "without connection level security, " - "must set 'winbind sealed pipes = false' and " - "'require strong key = false' to proceed: %s\n", - domain->name, nt_errstr(result))); + "must set 'winbind sealed pipes:%s = false' and " + "'require strong key:%s = false' to proceed: %s\n", + domain->name, domain->name, domain->name, + nt_errstr(result))); goto done; } -- 2.34.1 From 2d4faaf6eb2cc2cb0c13f46f348e2710c8f9e3cf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 24 Nov 2022 18:22:23 +0100 Subject: [PATCH 07/30] CVE-2022-38023 docs-xml/smbdotconf: change 'reject md5 servers' default to yes AES is supported by Windows >= 2008R2 and Samba >= 4.0 so there's no reason to allow md5 servers by default. Note the change in netlogon_creds_cli_context_global() is only cosmetic, but avoids confusion while reading the code. Check with: git show -U35 libcli/auth/netlogon_creds_cli.c BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 1c6c1129905d0c7a60018e7bf0f17a0fd198a584) --- docs-xml/smbdotconf/winbind/rejectmd5servers.xml | 7 +++++-- lib/param/loadparm.c | 1 + libcli/auth/netlogon_creds_cli.c | 4 ++-- source3/param/loadparm.c | 1 + 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml index 151b4676c57b..3bc4eaf7b02e 100644 --- a/docs-xml/smbdotconf/winbind/rejectmd5servers.xml +++ b/docs-xml/smbdotconf/winbind/rejectmd5servers.xml @@ -13,10 +13,13 @@ This will prevent downgrade attacks. The behavior can be controlled per netbios domain - by using 'reject md5 servers:NETBIOSDOMAIN = yes' as option. + by using 'reject md5 servers:NETBIOSDOMAIN = no' as option. + + The default changed from 'no' to 'yes, with the patches for CVE-2022-38023, + see https://bugzilla.samba.org/show_bug.cgi?id=15240 This option overrides the option. -no +yes diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c index d8646120e6bd..10157c95bc16 100644 --- a/lib/param/loadparm.c +++ b/lib/param/loadparm.c @@ -2669,6 +2669,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) lpcfg_do_global_parameter(lp_ctx, "winbind sealed pipes", "True"); lpcfg_do_global_parameter(lp_ctx, "winbind scan trusted domains", "False"); lpcfg_do_global_parameter(lp_ctx, "require strong key", "True"); + lpcfg_do_global_parameter(lp_ctx, "reject md5 servers", "True"); lpcfg_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR); lpcfg_do_global_parameter(lp_ctx, "ntp signd socket directory", dyn_NTP_SIGND_SOCKET_DIR); lpcfg_do_global_parameter_var(lp_ctx, "gpo update command", "%s/samba-gpupdate", dyn_SCRIPTSBINDIR); diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 848d993a3c66..52df5ab12a63 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -341,8 +341,8 @@ NTSTATUS netlogon_creds_cli_context_global(struct loadparm_context *lp_ctx, const char *client_computer; uint32_t proposed_flags; uint32_t required_flags = 0; - bool reject_md5_servers = false; - bool require_strong_key = false; + bool reject_md5_servers = true; + bool require_strong_key = true; int require_sign_or_seal = true; bool seal_secure_channel = true; enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 43838575f3bf..91bb3c08327b 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -666,6 +666,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) Globals.client_schannel = true; Globals.winbind_sealed_pipes = true; Globals.require_strong_key = true; + Globals.reject_md5_servers = true; Globals.server_schannel = true; Globals.read_raw = true; Globals.write_raw = true; -- 2.34.1 From 3157a6b132873fe1a641f7382e0dffae81445af0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Dec 2022 10:56:29 +0100 Subject: [PATCH 08/30] CVE-2022-38023 s4:rpc_server/netlogon: 'server schannel != yes' warning to dcesrv_interface_netlogon_bind This will simplify the following changes. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit e060ea5b3edbe3cba492062c9605f88fae212ee0) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 12ad78036d00..834e691bf90e 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -63,6 +63,21 @@ static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface) { + struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx; + int schannel = lpcfg_server_schannel(lp_ctx); + bool schannel_global_required = (schannel == true); + static bool warned_global_schannel_once = false; + + if (!schannel_global_required && !warned_global_schannel_once) { + /* + * We want admins to notice their misconfiguration! + */ + D_ERR("CVE-2020-1472(ZeroLogon): " + "Please configure 'server schannel = yes' (the default), " + "See https://bugzilla.samba.org/show_bug.cgi?id=14497\n"); + warned_global_schannel_once = true; + } + return dcesrv_interface_bind_reject_connect(context, iface); } @@ -630,7 +645,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; uint16_t opnum = dce_call->pkt.u.request.opnum; const char *opname = ""; - static bool warned_global_once = false; if (opnum < ndr_table_netlogon.num_calls) { opname = ndr_table_netlogon.calls[opnum].name; @@ -682,16 +696,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc return NT_STATUS_ACCESS_DENIED; } - if (!schannel_global_required && !warned_global_once) { - /* - * We want admins to notice their misconfiguration! - */ - DBG_ERR("CVE-2020-1472(ZeroLogon): " - "Please configure 'server schannel = yes', " - "See https://bugzilla.samba.org/show_bug.cgi?id=14497\n"); - warned_global_once = true; - } - if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { DBG_ERR("CVE-2020-1472(ZeroLogon): " "%s request (opnum[%u]) WITH schannel from " -- 2.34.1 From 28310ba1d9288ba7f4e58c90f591bb9ca0e2350e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 12 Dec 2022 14:03:50 +0100 Subject: [PATCH 09/30] CVE-2022-38023 s4:rpc_server/netlogon: add a lp_ctx variable to dcesrv_netr_creds_server_step_check() This will simplify the following changes. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 7baabbe9819cd5a2714e7ea4e57a0c23062c0150) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 834e691bf90e..16c0101d1ea0 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -636,8 +636,9 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc struct netr_Authenticator *return_authenticator, struct netlogon_creds_CredentialState **creds_out) { + struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; NTSTATUS nt_status; - int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx); + int schannel = lpcfg_server_schannel(lp_ctx); bool schannel_global_required = (schannel == true); bool schannel_required = schannel_global_required; const char *explicit_opt = NULL; @@ -653,7 +654,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc dcesrv_call_auth_info(dce_call, &auth_type, NULL); nt_status = schannel_check_creds_state(mem_ctx, - dce_call->conn->dce_ctx->lp_ctx, + lp_ctx, computer_name, received_authenticator, return_authenticator, @@ -668,7 +669,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc * need the explicit_opt pointer in order to * adjust the debug messages. */ - explicit_opt = lpcfg_get_parametric(dce_call->conn->dce_ctx->lp_ctx, + explicit_opt = lpcfg_get_parametric(lp_ctx, NULL, "server require schannel", creds->account_name); -- 2.34.1 From 0ba8ec7deae74b5d945278614f0634d920e2c3c7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 12 Dec 2022 14:03:50 +0100 Subject: [PATCH 10/30] CVE-2022-38023 s4:rpc_server/netlogon: add talloc_stackframe() to dcesrv_netr_creds_server_step_check() This will simplify the following changes. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 0e6a2ba83ef1be3c6a0f5514c21395121621a145) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 16c0101d1ea0..59386c4d5290 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -637,6 +637,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc struct netlogon_creds_CredentialState **creds_out) { struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; + TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS nt_status; int schannel = lpcfg_server_schannel(lp_ctx); bool schannel_global_required = (schannel == true); @@ -680,6 +681,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc if (schannel_required) { if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { *creds_out = creds; + TALLOC_FREE(frame); return NT_STATUS_OK; } @@ -687,13 +689,15 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc "%s request (opnum[%u]) without schannel from " "client_account[%s] client_computer_name[%s]\n", opname, opnum, - log_escape(mem_ctx, creds->account_name), - log_escape(mem_ctx, creds->computer_name)); + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name)); DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option " - "'server require schannel:%s = no' is needed! \n", - log_escape(mem_ctx, creds->account_name)); + "'server require schannel:%s = no' " + "might be needed for a legacy client.\n", + log_escape(frame, creds->account_name)); TALLOC_FREE(creds); ZERO_STRUCTP(return_authenticator); + TALLOC_FREE(frame); return NT_STATUS_ACCESS_DENIED; } @@ -702,13 +706,14 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc "%s request (opnum[%u]) WITH schannel from " "client_account[%s] client_computer_name[%s]\n", opname, opnum, - log_escape(mem_ctx, creds->account_name), - log_escape(mem_ctx, creds->computer_name)); + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name)); DBG_ERR("CVE-2020-1472(ZeroLogon): " "Option 'server require schannel:%s = no' not needed!?\n", - log_escape(mem_ctx, creds->account_name)); + log_escape(frame, creds->account_name)); *creds_out = creds; + TALLOC_FREE(frame); return NT_STATUS_OK; } @@ -718,24 +723,25 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc "%s request (opnum[%u]) without schannel from " "client_account[%s] client_computer_name[%s]\n", opname, opnum, - log_escape(mem_ctx, creds->account_name), - log_escape(mem_ctx, creds->computer_name)); + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name)); DBG_INFO("CVE-2020-1472(ZeroLogon): " "Option 'server require schannel:%s = no' still needed!\n", - log_escape(mem_ctx, creds->account_name)); + log_escape(frame, creds->account_name)); } else { DBG_ERR("CVE-2020-1472(ZeroLogon): " "%s request (opnum[%u]) without schannel from " "client_account[%s] client_computer_name[%s]\n", opname, opnum, - log_escape(mem_ctx, creds->account_name), - log_escape(mem_ctx, creds->computer_name)); + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name)); DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option " "'server require schannel:%s = no' might be needed!\n", - log_escape(mem_ctx, creds->account_name)); + log_escape(frame, creds->account_name)); } *creds_out = creds; + TALLOC_FREE(frame); return NT_STATUS_OK; } -- 2.34.1 From 8dcb681f7da0ab4505b8688e924aecc4f92432f0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Nov 2022 12:37:03 +0100 Subject: [PATCH 11/30] CVE-2022-38023 s4:rpc_server/netlogon: re-order checking in dcesrv_netr_creds_server_step_check() This will simplify the following changes. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit ec62151a2fb49ecbeaa3bf924f49a956832b735e) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 59386c4d5290..e33e0819242f 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -678,13 +678,27 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc schannel_required = lp_bool(explicit_opt); } - if (schannel_required) { - if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { - *creds_out = creds; - TALLOC_FREE(frame); - return NT_STATUS_OK; + if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + if (!schannel_required) { + DBG_ERR("CVE-2020-1472(ZeroLogon): " + "%s request (opnum[%u]) WITH schannel from " + "client_account[%s] client_computer_name[%s]\n", + opname, opnum, + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name)); + } + if (explicit_opt != NULL && !schannel_required) { + DBG_ERR("CVE-2020-1472(ZeroLogon): " + "Option 'server require schannel:%s = no' not needed!?\n", + log_escape(frame, creds->account_name)); } + *creds_out = creds; + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + if (schannel_required) { DBG_ERR("CVE-2020-1472(ZeroLogon): " "%s request (opnum[%u]) without schannel from " "client_account[%s] client_computer_name[%s]\n", @@ -701,23 +715,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc return NT_STATUS_ACCESS_DENIED; } - if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { - DBG_ERR("CVE-2020-1472(ZeroLogon): " - "%s request (opnum[%u]) WITH schannel from " - "client_account[%s] client_computer_name[%s]\n", - opname, opnum, - log_escape(frame, creds->account_name), - log_escape(frame, creds->computer_name)); - DBG_ERR("CVE-2020-1472(ZeroLogon): " - "Option 'server require schannel:%s = no' not needed!?\n", - log_escape(frame, creds->account_name)); - - *creds_out = creds; - TALLOC_FREE(frame); - return NT_STATUS_OK; - } - - if (explicit_opt != NULL) { DBG_INFO("CVE-2020-1472(ZeroLogon): " "%s request (opnum[%u]) without schannel from " -- 2.34.1 From 5589c6eb66ca856e60b19553ff731c726072e796 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Nov 2022 12:37:03 +0100 Subject: [PATCH 12/30] CVE-2022-38023 s4:rpc_server/netlogon: improve CVE-2020-1472(ZeroLogon) debug messages In order to avoid generating useless debug messages during make test, we will use 'CVE_2020_1472:warn_about_unused_debug_level = 3' and 'CVE_2020_1472:error_debug_level = 2' in order to avoid schannel warnings. Review with: git show -w BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 16ee03efc194d9c1c2c746f63236b977a419918d) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 147 +++++++++++++----- 1 file changed, 106 insertions(+), 41 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index e33e0819242f..ce01400ec88b 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -644,15 +644,34 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc bool schannel_required = schannel_global_required; const char *explicit_opt = NULL; struct netlogon_creds_CredentialState *creds = NULL; + int CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL, + "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR); + int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL, + "CVE_2020_1472", "error_debug_level", DBGLVL_ERR); + unsigned int dbg_lvl = DBGLVL_DEBUG; enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; uint16_t opnum = dce_call->pkt.u.request.opnum; const char *opname = ""; + const char *reason = ""; if (opnum < ndr_table_netlogon.num_calls) { opname = ndr_table_netlogon.calls[opnum].name; } - dcesrv_call_auth_info(dce_call, &auth_type, NULL); + dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); + + if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { + reason = "WITH SEALED"; + } else if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) { + reason = "WITH SIGNED"; + } else { + smb_panic("Schannel without SIGN/SEAL"); + } + } else { + reason = "WITHOUT"; + } nt_status = schannel_check_creds_state(mem_ctx, lp_ctx, @@ -679,62 +698,108 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc } if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { - if (!schannel_required) { - DBG_ERR("CVE-2020-1472(ZeroLogon): " - "%s request (opnum[%u]) WITH schannel from " - "client_account[%s] client_computer_name[%s]\n", - opname, opnum, - log_escape(frame, creds->account_name), - log_escape(frame, creds->computer_name)); + nt_status = NT_STATUS_OK; + + if (explicit_opt != NULL && !schannel_required) { + dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level); + } else if (!schannel_required) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); } + + DEBUG(dbg_lvl, ( + "CVE-2020-1472(ZeroLogon): " + "%s request (opnum[%u]) %s schannel from " + "client_account[%s] client_computer_name[%s] %s\n", + opname, opnum, reason, + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name), + nt_errstr(nt_status))); + if (explicit_opt != NULL && !schannel_required) { - DBG_ERR("CVE-2020-1472(ZeroLogon): " - "Option 'server require schannel:%s = no' not needed!?\n", - log_escape(frame, creds->account_name)); + DEBUG(CVE_2020_1472_warn_level, ( + "CVE-2020-1472(ZeroLogon): " + "Option 'server require schannel:%s = no' not needed for '%s'!\n", + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name))); } *creds_out = creds; TALLOC_FREE(frame); - return NT_STATUS_OK; + return nt_status; } if (schannel_required) { - DBG_ERR("CVE-2020-1472(ZeroLogon): " - "%s request (opnum[%u]) without schannel from " - "client_account[%s] client_computer_name[%s]\n", - opname, opnum, - log_escape(frame, creds->account_name), - log_escape(frame, creds->computer_name)); - DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option " - "'server require schannel:%s = no' " - "might be needed for a legacy client.\n", - log_escape(frame, creds->account_name)); + nt_status = NT_STATUS_ACCESS_DENIED; + + if (explicit_opt != NULL) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); + } else { + dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); + } + + DEBUG(dbg_lvl, ( + "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " + "%s request (opnum[%u]) %s schannel from " + "client_account[%s] client_computer_name[%s] %s\n", + opname, opnum, reason, + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name), + nt_errstr(nt_status))); + if (explicit_opt != NULL) { + D_NOTICE("CVE-2020-1472(ZeroLogon): Option " + "'server require schannel:%s = yes' " + "rejects access for client.\n", + log_escape(frame, creds->account_name)); + } else { + DEBUG(CVE_2020_1472_error_level, ( + "CVE-2020-1472(ZeroLogon): Check if option " + "'server require schannel:%s = no' " + "might be needed for a legacy client.\n", + log_escape(frame, creds->account_name))); + } TALLOC_FREE(creds); ZERO_STRUCTP(return_authenticator); TALLOC_FREE(frame); - return NT_STATUS_ACCESS_DENIED; + return nt_status; } + nt_status = NT_STATUS_OK; + if (explicit_opt != NULL) { - DBG_INFO("CVE-2020-1472(ZeroLogon): " - "%s request (opnum[%u]) without schannel from " - "client_account[%s] client_computer_name[%s]\n", - opname, opnum, - log_escape(frame, creds->account_name), - log_escape(frame, creds->computer_name)); - DBG_INFO("CVE-2020-1472(ZeroLogon): " - "Option 'server require schannel:%s = no' still needed!\n", - log_escape(frame, creds->account_name)); + dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); } else { - DBG_ERR("CVE-2020-1472(ZeroLogon): " - "%s request (opnum[%u]) without schannel from " - "client_account[%s] client_computer_name[%s]\n", - opname, opnum, - log_escape(frame, creds->account_name), - log_escape(frame, creds->computer_name)); - DBG_ERR("CVE-2020-1472(ZeroLogon): Check if option " - "'server require schannel:%s = no' might be needed!\n", - log_escape(frame, creds->account_name)); + dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); + } + + DEBUG(dbg_lvl, ( + "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " + "%s request (opnum[%u]) %s schannel from " + "client_account[%s] client_computer_name[%s] %s\n", + opname, opnum, reason, + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name), + nt_errstr(nt_status))); + + if (explicit_opt != NULL) { + D_INFO("CVE-2020-1472(ZeroLogon): Option " + "'server require schannel:%s = no' " + "still needed for '%s'!\n", + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name)); + } else { + /* + * admins should set + * server require schannel:COMPUTER$ = no + * in order to avoid the level 0 messages. + * Over time they can switch the global value + * to be strict. + */ + DEBUG(CVE_2020_1472_error_level, ( + "CVE-2020-1472(ZeroLogon): " + "Please use 'server require schannel:%s = no' " + "for '%s' to avoid this warning!\n", + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name))); } *creds_out = creds; -- 2.34.1 From 94f64296ad7de354af25b81b98f7d4153cabca43 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Nov 2022 12:26:01 +0100 Subject: [PATCH 13/30] CVE-2022-38023 selftest:Samba4: avoid global 'server schannel = auto' Instead of using the generic deprecated option use the specific server require schannel:COMPUTERACCOUNT = no in order to allow legacy tests for pass. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 63c96ea6c02981795e67336401143f2a8836992c) --- selftest/target/Samba4.pm | 40 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index dcf00e85e9c7..191aa3b749ee 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -1617,10 +1617,27 @@ sub provision_ad_dc_ntvfs($$$) dsdb event notification = true dsdb password event notification = true dsdb group change notification = true - server schannel = auto # override the new SMB2 only default client min protocol = CORE server min protocol = LANMAN1 + + CVE_2020_1472:warn_about_unused_debug_level = 3 + server require schannel:schannel0\$ = no + server require schannel:schannel1\$ = no + server require schannel:schannel2\$ = no + server require schannel:schannel3\$ = no + server require schannel:schannel4\$ = no + server require schannel:schannel5\$ = no + server require schannel:schannel6\$ = no + server require schannel:schannel7\$ = no + server require schannel:schannel8\$ = no + server require schannel:schannel9\$ = no + server require schannel:schannel10\$ = no + server require schannel:schannel11\$ = no + server require schannel:torturetest\$ = no + + # needed for 'samba.tests.auth_log' tests + server require schannel:LOCALDC\$ = no "; push (@{$extra_provision_options}, "--use-ntvfs"); my $ret = $self->provision($prefix, @@ -1969,8 +1986,22 @@ sub provision_ad_dc($$$$$$$) lpq cache time = 0 print notify backchannel = yes - server schannel = auto - auth event notification = true + CVE_2020_1472:warn_about_unused_debug_level = 3 + server require schannel:schannel0\$ = no + server require schannel:schannel1\$ = no + server require schannel:schannel2\$ = no + server require schannel:schannel3\$ = no + server require schannel:schannel4\$ = no + server require schannel:schannel5\$ = no + server require schannel:schannel6\$ = no + server require schannel:schannel7\$ = no + server require schannel:schannel8\$ = no + server require schannel:schannel9\$ = no + server require schannel:schannel10\$ = no + server require schannel:schannel11\$ = no + server require schannel:torturetest\$ = no + + auth event notification = true dsdb event notification = true dsdb password event notification = true dsdb group change notification = true @@ -2659,6 +2690,9 @@ sub setup_ad_dc_smb1 [global] client min protocol = CORE server min protocol = LANMAN1 + + # needed for 'samba.tests.auth_log' tests + server require schannel:ADDCSMB1\$ = no "; return _setup_ad_dc($self, $path, $conf_opts, "addcsmb1", "addom2.samba.example.com"); } -- 2.34.1 From 14efe15daa8600ba9be658ce98cb0d30a6e35a2c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 28 Nov 2022 15:02:13 +0100 Subject: [PATCH 14/30] CVE-2022-38023 s4:torture: use NETLOGON_NEG_SUPPORTS_AES by default For generic tests we should use the best available features. And AES will be required by default soon. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit cfd55a22cda113fbb2bfa373b54091dde1ea6e66) --- source4/torture/ntp/ntp_signd.c | 2 +- source4/torture/rpc/lsa.c | 4 ++-- source4/torture/rpc/netlogon.c | 24 ++++++++++++------------ source4/torture/rpc/samba3rpc.c | 15 ++++++++++++--- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/source4/torture/ntp/ntp_signd.c b/source4/torture/ntp/ntp_signd.c index 124c9604871b..6d482bfdee16 100644 --- a/source4/torture/ntp/ntp_signd.c +++ b/source4/torture/ntp/ntp_signd.c @@ -70,7 +70,7 @@ static bool test_ntp_signd(struct torture_context *tctx, uint32_t rid; const char *machine_name; const struct samr_Password *pwhash = cli_credentials_get_nt_hash(credentials, mem_ctx); - uint32_t negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; struct sign_request sign_req; struct signed_reply signed_reply; diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index d430ee571081..d22546862d5b 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -4408,7 +4408,7 @@ static bool check_dom_trust_pw(struct dcerpc_pipe *p, torture_assert_ntstatus_ok(tctx, status, "dcerpc_pipe_connect_b"); ok = check_pw_with_ServerAuthenticate3(p1, tctx, - NETLOGON_NEG_AUTH2_ADS_FLAGS, + NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES, server_name, incoming_creds, &creds); torture_assert_int_equal(tctx, ok, expected_result, @@ -4505,7 +4505,7 @@ static bool check_dom_trust_pw(struct dcerpc_pipe *p, torture_assert_ntstatus_ok(tctx, status, "dcerpc_pipe_connect_b"); ok = check_pw_with_ServerAuthenticate3(p2, tctx, - NETLOGON_NEG_AUTH2_ADS_FLAGS, + NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES, server_name, incoming_creds, &creds); torture_assert(tctx, ok, "check_pw_with_ServerAuthenticate3 with changed password"); diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index 59d7feb43f1d..1f068eb78265 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -191,7 +191,7 @@ bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context *tctx, /* This allows the tests to continue against the more fussy windows 2008 */ if (NT_STATUS_EQUAL(a.out.result, NT_STATUS_DOWNGRADE_DETECTED)) { - return test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, + return test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES, credentials, cli_credentials_get_secure_channel_type(credentials), creds_out); @@ -431,7 +431,7 @@ bool test_SetupCredentialsDowngrade(struct torture_context *tctx, "ServerAuthenticate3 failed"); torture_assert_ntstatus_equal(tctx, a.out.result, NT_STATUS_DOWNGRADE_DETECTED, "ServerAuthenticate3 should have failed"); - negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; creds = netlogon_creds_client_init(tctx, a.in.account_name, a.in.computer_name, a.in.secure_channel_type, @@ -498,7 +498,7 @@ static bool test_ServerReqChallenge( const char *machine_name; struct dcerpc_binding_handle *b = p->binding_handle; struct netr_ServerAuthenticate2 a; - uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; uint32_t out_negotiate_flags = 0; const struct samr_Password *mach_password = NULL; enum netr_SchannelType sec_chan_type = 0; @@ -570,7 +570,7 @@ static bool test_ServerReqChallenge_zero_challenge( const char *machine_name; struct dcerpc_binding_handle *b = p->binding_handle; struct netr_ServerAuthenticate2 a; - uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; uint32_t out_negotiate_flags = 0; const struct samr_Password *mach_password = NULL; enum netr_SchannelType sec_chan_type = 0; @@ -647,7 +647,7 @@ static bool test_ServerReqChallenge_5_repeats( const char *machine_name; struct dcerpc_binding_handle *b = p->binding_handle; struct netr_ServerAuthenticate2 a; - uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; uint32_t out_negotiate_flags = 0; const struct samr_Password *mach_password = NULL; enum netr_SchannelType sec_chan_type = 0; @@ -731,7 +731,7 @@ static bool test_ServerReqChallenge_4_repeats( const char *machine_name; struct dcerpc_binding_handle *b = p->binding_handle; struct netr_ServerAuthenticate2 a; - uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t in_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; uint32_t out_negotiate_flags = 0; const struct samr_Password *mach_password = NULL; enum netr_SchannelType sec_chan_type = 0; @@ -1527,7 +1527,7 @@ static bool test_SetPassword2_all_zeros( struct netr_CryptPassword new_password; struct dcerpc_pipe *p = NULL; struct dcerpc_binding_handle *b = NULL; - uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; /* no AES desired here */ if (!test_SetupCredentials2( p1, @@ -1603,7 +1603,7 @@ static bool test_SetPassword2_maximum_length_password( struct netr_CryptPassword new_password; struct dcerpc_pipe *p = NULL; struct dcerpc_binding_handle *b = NULL; - uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; DATA_BLOB new_random_pass = data_blob_null; if (!test_SetupCredentials2( @@ -1686,7 +1686,7 @@ static bool test_SetPassword2_all_zero_password( struct netr_CryptPassword new_password; struct dcerpc_pipe *p = NULL; struct dcerpc_binding_handle *b = NULL; - uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + uint32_t flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; /* no AES desired here */ if (!test_SetupCredentials2( p1, @@ -4046,7 +4046,7 @@ static bool test_netr_GetForestTrustInformation(struct torture_context *tctx, struct dcerpc_pipe *p = NULL; struct dcerpc_binding_handle *b = NULL; - if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, + if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES, machine_credentials, &creds)) { return false; } @@ -4985,7 +4985,7 @@ static bool test_GetDomainInfo(struct torture_context *tctx, torture_comment(tctx, "Testing netr_LogonGetDomainInfo\n"); - if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, + if (!test_SetupCredentials3(p1, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES, machine_credentials, &creds)) { return false; } @@ -5562,7 +5562,7 @@ static bool test_GetDomainInfo_async(struct torture_context *tctx, torture_comment(tctx, "Testing netr_LogonGetDomainInfo - async count %d\n", ASYNC_COUNT); - if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, + if (!test_SetupCredentials3(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES, machine_credentials, &creds)) { return false; } diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c index 39e43e5fcdbe..36eabdc488d9 100644 --- a/source4/torture/rpc/samba3rpc.c +++ b/source4/torture/rpc/samba3rpc.c @@ -1071,7 +1071,7 @@ static bool auth2(struct torture_context *tctx, goto done; } - negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES; E_md4hash(cli_credentials_get_password(wks_cred), mach_pw.hash); a.in.server_name = talloc_asprintf( @@ -1260,10 +1260,19 @@ static bool schan(struct torture_context *tctx, E_md4hash(cli_credentials_get_password(user_creds), pinfo.ntpassword.hash); - netlogon_creds_arcfour_crypt(creds_state, pinfo.ntpassword.hash, 16); - logon.password = &pinfo; + /* + * We don't use this here: + * + * netlogon_creds_encrypt_samlogon_logon(creds_state, + * NetlogonInteractiveInformation, + * &logon); + * + * in order to detect bugs + */ + netlogon_creds_aes_encrypt(creds_state, pinfo.ntpassword.hash, 16); + r.in.logon_level = NetlogonInteractiveInformation; r.in.logon = &logon; r.out.return_authenticator = &return_authenticator; -- 2.34.1 From b7bd51a393988883936048a0fd9d790d0e03481f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 25 Nov 2022 09:54:17 +0100 Subject: [PATCH 15/30] CVE-2022-38023 s4:rpc_server/netlogon: split out dcesrv_netr_ServerAuthenticate3_check_downgrade() We'll soon make it possible to use 'reject md5 servers:CLIENTACCOUNT$ = no', which means we'll need the downgrade detection in more places. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit b6339fd1dcbe903e73efeea074ab0bd04ef83561) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 114 ++++++++++-------- 1 file changed, 67 insertions(+), 47 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index ce01400ec88b..82e3df055e7f 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -125,6 +125,67 @@ static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_cal return NT_STATUS_OK; } +static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade( + struct dcesrv_call_state *dce_call, + struct netr_ServerAuthenticate3 *r, + struct netlogon_server_pipe_state *pipe_state, + uint32_t negotiate_flags, + NTSTATUS orig_status) +{ + struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; + bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx); + bool reject_des_client = !allow_nt4_crypto; + bool reject_md5_client = lpcfg_reject_md5_clients(lp_ctx); + + if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { + reject_des_client = false; + } + + if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + reject_des_client = false; + reject_md5_client = false; + } + + if (reject_des_client || reject_md5_client) { + /* + * Here we match Windows 2012 and return no flags. + */ + *r->out.negotiate_flags = 0; + return NT_STATUS_DOWNGRADE_DETECTED; + } + + /* + * This talloc_free is important to prevent re-use of the + * challenge. We have to delay it this far due to NETApp + * servers per: + * https://bugzilla.samba.org/show_bug.cgi?id=11291 + */ + TALLOC_FREE(pipe_state); + + /* + * At this point we must also cleanup the TDB cache + * entry, if we fail the client needs to call + * netr_ServerReqChallenge again. + * + * Note: this handles a non existing record just fine, + * the r->in.computer_name might not be the one used + * in netr_ServerReqChallenge(), but we are trying to + * just tidy up the normal case to prevent re-use. + */ + schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx, + r->in.computer_name); + + /* + * According to Microsoft (see bugid #6099) + * Windows 7 looks at the negotiate_flags + * returned in this structure *even if the + * call fails with access denied! + */ + *r->out.negotiate_flags = negotiate_flags; + + return orig_status; +} + /* * Do the actual processing of a netr_ServerAuthenticate3 message. * called from dcesrv_netr_ServerAuthenticate3, which handles the logging. @@ -152,11 +213,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( "objectSid", "samAccountName", NULL}; uint32_t server_flags = 0; uint32_t negotiate_flags = 0; - bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(dce_call->conn->dce_ctx->lp_ctx); - bool reject_des_client = !allow_nt4_crypto; - bool reject_md5_client = lpcfg_reject_md5_clients(dce_call->conn->dce_ctx->lp_ctx); ZERO_STRUCTP(r->out.return_credentials); + *r->out.negotiate_flags = 0; *r->out.rid = 0; pipe_state = dcesrv_iface_state_find_conn(dce_call, @@ -243,52 +302,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( negotiate_flags = *r->in.negotiate_flags & server_flags; - if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { - reject_des_client = false; - } - - if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { - reject_des_client = false; - reject_md5_client = false; - } - - if (reject_des_client || reject_md5_client) { - /* - * Here we match Windows 2012 and return no flags. - */ - *r->out.negotiate_flags = 0; - return NT_STATUS_DOWNGRADE_DETECTED; + nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_OK); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; } - /* - * This talloc_free is important to prevent re-use of the - * challenge. We have to delay it this far due to NETApp - * servers per: - * https://bugzilla.samba.org/show_bug.cgi?id=11291 - */ - TALLOC_FREE(pipe_state); - - /* - * At this point we must also cleanup the TDB cache - * entry, if we fail the client needs to call - * netr_ServerReqChallenge again. - * - * Note: this handles a non existing record just fine, - * the r->in.computer_name might not be the one used - * in netr_ServerReqChallenge(), but we are trying to - * just tidy up the normal case to prevent re-use. - */ - schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx, - r->in.computer_name); - - /* - * According to Microsoft (see bugid #6099) - * Windows 7 looks at the negotiate_flags - * returned in this structure *even if the - * call fails with access denied! - */ - *r->out.negotiate_flags = negotiate_flags; - switch (r->in.secure_channel_type) { case SEC_CHAN_WKSTA: case SEC_CHAN_DNS_DOMAIN: -- 2.34.1 From 548325d1e837123e7e356de6849daf62f12cabfd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 25 Nov 2022 10:10:33 +0100 Subject: [PATCH 16/30] CVE-2022-38023 s4:rpc_server/netlogon: require aes if weak crypto is disabled BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 4c7f84798acd1e3218209d66d1a92e9f42954d51) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 9 +++++++++ source4/torture/rpc/netlogon_crypto.c | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 82e3df055e7f..51e8dd42cdce 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -137,6 +137,15 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade( bool reject_des_client = !allow_nt4_crypto; bool reject_md5_client = lpcfg_reject_md5_clients(lp_ctx); + /* + * If weak cryto is disabled, do not announce that we support RC4. + */ + if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) { + /* Without RC4 and DES we require AES */ + reject_des_client = true; + reject_md5_client = true; + } + if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { reject_des_client = false; } diff --git a/source4/torture/rpc/netlogon_crypto.c b/source4/torture/rpc/netlogon_crypto.c index 05beb2b77b3b..85844604ee27 100644 --- a/source4/torture/rpc/netlogon_crypto.c +++ b/source4/torture/rpc/netlogon_crypto.c @@ -150,7 +150,7 @@ static bool test_ServerAuth3Crypto(struct dcerpc_pipe *p, force_client_rc4) { torture_assert_ntstatus_equal(tctx, a.out.result, - NT_STATUS_ACCESS_DENIED, + NT_STATUS_DOWNGRADE_DETECTED, "Unexpected status code"); return false; } -- 2.34.1 From 2d179d5d7cd6a47a1a7922f09b63234a467bdad3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 24 Nov 2022 18:26:18 +0100 Subject: [PATCH 17/30] CVE-2022-38023 docs-xml/smbdotconf: change 'reject md5 clients' default to yes AES is supported by Windows Server >= 2008R2, Windows (Client) >= 7 and Samba >= 4.0, so there's no reason to allow md5 clients by default. However some third party domain members may need it. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit c8e53394b98b128ed460a6111faf05dfbad980d1) --- docs-xml/smbdotconf/logon/rejectmd5clients.xml | 11 ++++++++--- lib/param/loadparm.c | 1 + selftest/target/Samba4.pm | 4 ++++ source3/param/loadparm.c | 1 + 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/docs-xml/smbdotconf/logon/rejectmd5clients.xml b/docs-xml/smbdotconf/logon/rejectmd5clients.xml index 0bb9f6f6c8ec..edcbe02e99a3 100644 --- a/docs-xml/smbdotconf/logon/rejectmd5clients.xml +++ b/docs-xml/smbdotconf/logon/rejectmd5clients.xml @@ -7,11 +7,16 @@ only in 'active directory domain controller' mode), will reject clients which does not support NETLOGON_NEG_SUPPORTS_AES. - You can set this to yes if all domain members support aes. - This will prevent downgrade attacks. + Support for NETLOGON_NEG_SUPPORTS_AES was added in Windows + starting with Server 2008R2 and Windows 7, it's available in Samba + starting with 4.0, however third party domain members like NetApp ONTAP + still uses RC4 (HMAC-MD5), see https://www.samba.org/samba/security/CVE-2022-38023.html for more details. + + The default changed from 'no' to 'yes', with the patches for CVE-2022-38023, + see https://bugzilla.samba.org/show_bug.cgi?id=15240 This option overrides the 'allow nt4 crypto' option. -no +yes diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c index 10157c95bc16..e509cf85bb89 100644 --- a/lib/param/loadparm.c +++ b/lib/param/loadparm.c @@ -2729,6 +2729,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) lpcfg_do_global_parameter(lp_ctx, "winbind nss info", "template"); lpcfg_do_global_parameter(lp_ctx, "server schannel", "True"); + lpcfg_do_global_parameter(lp_ctx, "reject md5 clients", "True"); lpcfg_do_global_parameter(lp_ctx, "short preserve case", "True"); diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 191aa3b749ee..d0e5a53d9fb3 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -1621,6 +1621,8 @@ sub provision_ad_dc_ntvfs($$$) client min protocol = CORE server min protocol = LANMAN1 + reject md5 clients = no + CVE_2020_1472:warn_about_unused_debug_level = 3 server require schannel:schannel0\$ = no server require schannel:schannel1\$ = no @@ -1986,6 +1988,8 @@ sub provision_ad_dc($$$$$$$) lpq cache time = 0 print notify backchannel = yes + reject md5 clients = no + CVE_2020_1472:warn_about_unused_debug_level = 3 server require schannel:schannel0\$ = no server require schannel:schannel1\$ = no diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 91bb3c08327b..c88d241bcf78 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -668,6 +668,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) Globals.require_strong_key = true; Globals.reject_md5_servers = true; Globals.server_schannel = true; + Globals.reject_md5_clients = true; Globals.read_raw = true; Globals.write_raw = true; Globals.null_passwords = false; -- 2.34.1 From 2c9f18c158860c33522d333da6c65e3e5ccb385f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 25 Nov 2022 10:31:08 +0100 Subject: [PATCH 18/30] CVE-2022-38023 s4:rpc_server/netlogon: defer downgrade check until we found the account in our SAM We'll soon make it possible to use 'reject md5 servers:CLIENTACCOUNT$ = no', which means we'll need use the account name from our SAM. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit b09f51eefc311bbb1525efd1dc7b9a837f7ec3c2) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 76 +++++++++++++------ 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 51e8dd42cdce..bf545adc45a9 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -311,13 +311,6 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( negotiate_flags = *r->in.negotiate_flags & server_flags; - nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade( - dce_call, r, pipe_state, negotiate_flags, - NT_STATUS_OK); - if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; - } - switch (r->in.secure_channel_type) { case SEC_CHAN_WKSTA: case SEC_CHAN_DNS_DOMAIN: @@ -326,16 +319,22 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( case SEC_CHAN_RODC: break; case SEC_CHAN_NULL: - return NT_STATUS_INVALID_PARAMETER; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_INVALID_PARAMETER); default: DEBUG(1, ("Client asked for an invalid secure channel type: %d\n", r->in.secure_channel_type)); - return NT_STATUS_INVALID_PARAMETER; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_INVALID_PARAMETER); } sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call); if (sam_ctx == NULL) { - return NT_STATUS_INVALID_SYSTEM_SERVICE; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_INVALID_SYSTEM_SERVICE); } if (r->in.secure_channel_type == SEC_CHAN_DOMAIN || @@ -364,16 +363,22 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( encoded_name = ldb_binary_encode_string(mem_ctx, r->in.account_name); if (encoded_name == NULL) { - return NT_STATUS_NO_MEMORY; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_NO_MEMORY); } len = strlen(encoded_name); if (len < 2) { - return NT_STATUS_NO_TRUST_SAM_ACCOUNT; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_NO_TRUST_SAM_ACCOUNT); } if (require_trailer && encoded_name[len - 1] != trailer) { - return NT_STATUS_NO_TRUST_SAM_ACCOUNT; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_NO_TRUST_SAM_ACCOUNT); } encoded_name[len - 1] = '\0'; @@ -391,30 +396,42 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( "but there's no tdo for [%s] => [%s] \n", log_escape(mem_ctx, r->in.account_name), encoded_name)); - return NT_STATUS_NO_TRUST_SAM_ACCOUNT; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_NO_TRUST_SAM_ACCOUNT); } if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + nt_status); } nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx, &curNtHash, &prevNtHash); if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) { - return NT_STATUS_NO_TRUST_SAM_ACCOUNT; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_NO_TRUST_SAM_ACCOUNT); } if (!NT_STATUS_IS_OK(nt_status)) { - return nt_status; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + nt_status); } flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL); if (flatname == NULL) { - return NT_STATUS_NO_TRUST_SAM_ACCOUNT; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_NO_TRUST_SAM_ACCOUNT); } *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname); if (*trust_account_for_search == NULL) { - return NT_STATUS_NO_MEMORY; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_NO_MEMORY); } } else { *trust_account_for_search = r->in.account_name; @@ -429,14 +446,18 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( if (num_records == 0) { DEBUG(3,("Couldn't find user [%s] in samdb.\n", log_escape(mem_ctx, r->in.account_name))); - return NT_STATUS_NO_TRUST_SAM_ACCOUNT; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_NO_TRUST_SAM_ACCOUNT); } if (num_records > 1) { DEBUG(0,("Found %d records matching user [%s]\n", num_records, log_escape(mem_ctx, r->in.account_name))); - return NT_STATUS_INTERNAL_DB_CORRUPTION; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_INTERNAL_DB_CORRUPTION); } *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0], @@ -445,9 +466,18 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( if (*trust_account_in_db == NULL) { DEBUG(0,("No samAccountName returned in record matching user [%s]\n", r->in.account_name)); - return NT_STATUS_INTERNAL_DB_CORRUPTION; + return dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_INTERNAL_DB_CORRUPTION); } - + + nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade( + dce_call, r, pipe_state, negotiate_flags, + NT_STATUS_OK); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0); if (user_account_control & UF_ACCOUNTDISABLE) { -- 2.34.1 From fb1f31690d4f2e1498c2f7966543e99a3f239987 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 25 Nov 2022 13:13:36 +0100 Subject: [PATCH 19/30] CVE-2022-38023 s4:rpc_server/netlogon: add 'server reject md5 schannel:COMPUTERACCOUNT = no' and 'allow nt4 crypto:COMPUTERACCOUNT = yes' This makes it more flexible when we change the global default to 'reject md5 servers = yes'. 'allow nt4 crypto = no' is already the default. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 69b36541606d7064de9648cd54b35adfdf8f0e8f) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 58 ++++++++++++++++++- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index bf545adc45a9..a6e4499d5add 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -130,12 +130,48 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade( struct netr_ServerAuthenticate3 *r, struct netlogon_server_pipe_state *pipe_state, uint32_t negotiate_flags, + const char *trust_account_in_db, NTSTATUS orig_status) { struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; - bool allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx); - bool reject_des_client = !allow_nt4_crypto; - bool reject_md5_client = lpcfg_reject_md5_clients(lp_ctx); + bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx); + bool account_allow_nt4_crypto = global_allow_nt4_crypto; + const char *explicit_nt4_opt = NULL; + bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx); + bool account_reject_md5_client = global_reject_md5_client; + const char *explicit_md5_opt = NULL; + bool reject_des_client; + bool allow_nt4_crypto; + bool reject_md5_client; + + /* + * We don't use lpcfg_parm_bool(), as we + * need the explicit_opt pointer in order to + * adjust the debug messages. + */ + + if (trust_account_in_db != NULL) { + explicit_nt4_opt = lpcfg_get_parametric(lp_ctx, + NULL, + "allow nt4 crypto", + trust_account_in_db); + } + if (explicit_nt4_opt != NULL) { + account_allow_nt4_crypto = lp_bool(explicit_nt4_opt); + } + allow_nt4_crypto = account_allow_nt4_crypto; + if (trust_account_in_db != NULL) { + explicit_md5_opt = lpcfg_get_parametric(lp_ctx, + NULL, + "server reject md5 schannel", + trust_account_in_db); + } + if (explicit_md5_opt != NULL) { + account_reject_md5_client = lp_bool(explicit_md5_opt); + } + reject_md5_client = account_reject_md5_client; + + reject_des_client = !allow_nt4_crypto; /* * If weak cryto is disabled, do not announce that we support RC4. @@ -321,12 +357,14 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( case SEC_CHAN_NULL: return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ NT_STATUS_INVALID_PARAMETER); default: DEBUG(1, ("Client asked for an invalid secure channel type: %d\n", r->in.secure_channel_type)); return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ NT_STATUS_INVALID_PARAMETER); } @@ -334,6 +372,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( if (sam_ctx == NULL) { return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ NT_STATUS_INVALID_SYSTEM_SERVICE); } @@ -365,6 +404,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( if (encoded_name == NULL) { return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ NT_STATUS_NO_MEMORY); } @@ -372,12 +412,14 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( if (len < 2) { return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ NT_STATUS_NO_TRUST_SAM_ACCOUNT); } if (require_trailer && encoded_name[len - 1] != trailer) { return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ NT_STATUS_NO_TRUST_SAM_ACCOUNT); } encoded_name[len - 1] = '\0'; @@ -398,11 +440,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( encoded_name)); return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ NT_STATUS_NO_TRUST_SAM_ACCOUNT); } if (!NT_STATUS_IS_OK(nt_status)) { return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ nt_status); } @@ -412,11 +456,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) { return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ NT_STATUS_NO_TRUST_SAM_ACCOUNT); } if (!NT_STATUS_IS_OK(nt_status)) { return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ nt_status); } @@ -424,6 +470,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( if (flatname == NULL) { return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ NT_STATUS_NO_TRUST_SAM_ACCOUNT); } @@ -431,6 +478,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( if (*trust_account_for_search == NULL) { return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ NT_STATUS_NO_MEMORY); } } else { @@ -448,6 +496,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( log_escape(mem_ctx, r->in.account_name))); return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ NT_STATUS_NO_TRUST_SAM_ACCOUNT); } @@ -457,6 +506,7 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( log_escape(mem_ctx, r->in.account_name))); return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ NT_STATUS_INTERNAL_DB_CORRUPTION); } @@ -468,11 +518,13 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper( r->in.account_name)); return dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + NULL, /* trust_account_in_db */ NT_STATUS_INTERNAL_DB_CORRUPTION); } nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade( dce_call, r, pipe_state, negotiate_flags, + *trust_account_in_db, NT_STATUS_OK); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; -- 2.34.1 From 41d64ebc813440e809909076c98de25084c4731b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 25 Nov 2022 13:31:14 +0100 Subject: [PATCH 20/30] CVE-2022-38023 docs-xml/smbdotconf: document "allow nt4 crypto:COMPUTERACCOUNT = no" BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit bd429d025981b445bf63935063e8e302bfab3f9b) --- docs-xml/smbdotconf/logon/allownt4crypto.xml | 76 +++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/docs-xml/smbdotconf/logon/allownt4crypto.xml b/docs-xml/smbdotconf/logon/allownt4crypto.xml index 06afcef73b1b..bbd03a42db74 100644 --- a/docs-xml/smbdotconf/logon/allownt4crypto.xml +++ b/docs-xml/smbdotconf/logon/allownt4crypto.xml @@ -1,11 +1,18 @@ + + This option is deprecated and will be removed in future, + as it is a security problem if not set to "no" (which will be + the hardcoded behavior in future). + + This option controls whether the netlogon server (currently only in 'active directory domain controller' mode), will - reject clients which does not support NETLOGON_NEG_STRONG_KEYS + reject clients which do not support NETLOGON_NEG_STRONG_KEYS nor NETLOGON_NEG_SUPPORTS_AES. This option was added with Samba 4.2.0. It may lock out clients @@ -18,8 +25,73 @@ "allow nt4 crypto = yes" allows weak crypto to be negotiated, maybe via downgrade attacks. - This option is over-ridden by the 'reject md5 clients' option. + Avoid using this option! Use explicit 'yes' instead! + Which is available with the patches for + CVE-2022-38023 + see https://bugzilla.samba.org/show_bug.cgi?id=15240 + + + Samba will log an error in the log files at log level 0 + if legacy a client is rejected or allowed without an explicit, + 'yes' option + for the client. The message will indicate + the explicit 'yes' + line to be added, if the legacy client software requires it. (The log level can be adjusted with + '1' + in order to complain only at a higher log level). + + + This allows admins to use "yes" only for a short grace period, + in order to collect the explicit + 'yes' options. + + This option is over-ridden by the 'yes' option. no + + + + + If you still have legacy domain members which required 'allow nt4 crypto = yes', + it is possible to specify an explicit exception per computer account + by using 'allow nt4 crypto:COMPUTERACCOUNT = yes' as option. + Note that COMPUTERACCOUNT has to be the sAMAccountName value of + the computer account (including the trailing '$' sign). + + + + Samba will log a complaint in the log files at log level 0 + about the security problem if the option is set to "yes", + but the related computer does not require it. + (The log level can be adjusted with + '1' + in order to complain only at a higher log level). + + + + Samba will log a warning in the log files at log level 5, + if a setting is still needed for the specified computer account. + + + + See CVE-2022-38023, + https://bugzilla.samba.org/show_bug.cgi?id=15240. + + + This option overrides the option. + + This option is over-ridden by the 'yes' option. + + + allow nt4 crypto:LEGACYCOMPUTER1$ = yes + allow nt4 crypto:NASBOX$ = yes + allow nt4 crypto:LEGACYCOMPUTER2$ = yes + + + + -- 2.34.1 From 7f5e36250fa7121435f315cffa7b7059d3fe40a8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 25 Nov 2022 14:02:11 +0100 Subject: [PATCH 21/30] CVE-2022-38023 docs-xml/smbdotconf: document "server reject md5 schannel:COMPUTERACCOUNT" BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 2ad302b42254e3c2800aaf11669fe2e6d55fa8a1) --- docs-xml/smbdotconf/logon/allownt4crypto.xml | 13 ++- .../smbdotconf/logon/rejectmd5clients.xml | 96 ++++++++++++++++++- 2 files changed, 103 insertions(+), 6 deletions(-) diff --git a/docs-xml/smbdotconf/logon/allownt4crypto.xml b/docs-xml/smbdotconf/logon/allownt4crypto.xml index bbd03a42db74..ee63e6cc2453 100644 --- a/docs-xml/smbdotconf/logon/allownt4crypto.xml +++ b/docs-xml/smbdotconf/logon/allownt4crypto.xml @@ -45,7 +45,9 @@ in order to collect the explicit 'yes' options. - This option is over-ridden by the 'yes' option. + This option is over-ridden by the effective value of 'yes' from + the '' + and/or '' options. no @@ -85,12 +87,19 @@ This option overrides the option. - This option is over-ridden by the 'yes' option. + This option is over-ridden by the effective value of 'yes' from + the '' + and/or '' options. + Which means 'yes' + is only useful in combination with 'no' allow nt4 crypto:LEGACYCOMPUTER1$ = yes + server reject md5 schannel:LEGACYCOMPUTER1$ = no allow nt4 crypto:NASBOX$ = yes + server reject md5 schannel:NASBOX$ = no allow nt4 crypto:LEGACYCOMPUTER2$ = yes + server reject md5 schannel:LEGACYCOMPUTER2$ = no diff --git a/docs-xml/smbdotconf/logon/rejectmd5clients.xml b/docs-xml/smbdotconf/logon/rejectmd5clients.xml index edcbe02e99a3..fe7701d92772 100644 --- a/docs-xml/smbdotconf/logon/rejectmd5clients.xml +++ b/docs-xml/smbdotconf/logon/rejectmd5clients.xml @@ -1,8 +1,15 @@ + + This option is deprecated and will be removed in a future release, + as it is a security problem if not set to "yes" (which will be + the hardcoded behavior in the future). + + This option controls whether the netlogon server (currently only in 'active directory domain controller' mode), will reject clients which does not support NETLOGON_NEG_SUPPORTS_AES. @@ -10,13 +17,94 @@ Support for NETLOGON_NEG_SUPPORTS_AES was added in Windows starting with Server 2008R2 and Windows 7, it's available in Samba starting with 4.0, however third party domain members like NetApp ONTAP - still uses RC4 (HMAC-MD5), see https://www.samba.org/samba/security/CVE-2022-38023.html for more details. + still uses RC4 (HMAC-MD5), see + https://www.samba.org/samba/security/CVE-2022-38023.html + for more details. + + + The default changed from 'no' to 'yes', with the patches for + CVE-2022-38023 + see https://bugzilla.samba.org/show_bug.cgi?id=15240. + + + Avoid using this option! Use an explicit per machine account + '' instead! + Which is available with the patches for + CVE-2022-38023 + see https://bugzilla.samba.org/show_bug.cgi?id=15240. + - The default changed from 'no' to 'yes', with the patches for CVE-2022-38023, - see https://bugzilla.samba.org/show_bug.cgi?id=15240 + + Samba will log an error in the log files at log level 0 + if legacy a client is rejected or allowed without an explicit, + 'no' option + for the client. The message will indicate + the explicit 'no' + line to be added, if the legacy client software requires it. (The log level can be adjusted with + '1' + in order to complain only at a higher log level). + - This option overrides the 'allow nt4 crypto' option. + This allows admins to use "no" only for a short grace period, + in order to collect the explicit + 'no' options. + + When set to 'yes' this option overrides the + '' and + '' options and implies + 'no'. + yes + + + + + If you still have legacy domain members or trusted domains, + which required "reject md5 clients = no" before, + it is possible to specify an explicit exception per computer account + by setting 'server reject md5 schannel:COMPUTERACCOUNT = no'. + Note that COMPUTERACCOUNT has to be the sAMAccountName value of + the computer account (including the trailing '$' sign). + + + + Samba will log a complaint in the log files at log level 0 + about the security problem if the option is set to "no", + but the related computer does not require it. + (The log level can be adjusted with + '1' + in order to complain only at a higher log level). + + + + Samba will log a warning in the log files at log level 5 + if a setting is still needed for the specified computer account. + + + + See CVE-2022-38023, + https://bugzilla.samba.org/show_bug.cgi?id=15240. + + + This option overrides the option. + + When set to 'yes' this option overrides the + '' and + '' options and implies + 'no'. + + + + server reject md5 schannel:LEGACYCOMPUTER1$ = no + server reject md5 schannel:NASBOX$ = no + server reject md5 schannel:LEGACYCOMPUTER2$ = no + + + + -- 2.34.1 From 3c9bb4c8d233909e825818f7975d734824465d50 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 25 Nov 2022 13:13:36 +0100 Subject: [PATCH 22/30] CVE-2022-38023 s4:rpc_server/netlogon: debug 'reject md5 servers' and 'allow nt4 crypto' misconfigurations This allows the admin to notice what's wrong in order to adjust the configuration if required. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 43df4be35950f491864ae8ada05d51b42a556381) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index a6e4499d5add..ec5807ef22af 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -64,10 +64,34 @@ static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context const struct dcesrv_interface *iface) { struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx; + bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx); + bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx); int schannel = lpcfg_server_schannel(lp_ctx); bool schannel_global_required = (schannel == true); + static bool warned_global_nt4_once = false; + static bool warned_global_md5_once = false; static bool warned_global_schannel_once = false; + if (global_allow_nt4_crypto && !warned_global_nt4_once) { + /* + * We want admins to notice their misconfiguration! + */ + D_ERR("CVE-2022-38023 (and others): " + "Please configure 'allow nt4 crypto = no' (the default), " + "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); + warned_global_nt4_once = true; + } + + if (!global_reject_md5_client && !warned_global_md5_once) { + /* + * We want admins to notice their misconfiguration! + */ + D_ERR("CVE-2022-38023: " + "Please configure 'reject md5 clients = yes' (the default), " + "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); + warned_global_md5_once = true; + } + if (!schannel_global_required && !warned_global_schannel_once) { /* * We want admins to notice their misconfiguration! @@ -143,6 +167,12 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade( bool reject_des_client; bool allow_nt4_crypto; bool reject_md5_client; + bool need_des = true; + bool need_md5 = true; + int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL, + "CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR); + int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL, + "CVE_2022_38023", "error_debug_level", DBGLVL_ERR); /* * We don't use lpcfg_parm_bool(), as we @@ -183,19 +213,84 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade( } if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { + need_des = false; reject_des_client = false; } if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + need_des = false; + need_md5 = false; reject_des_client = false; reject_md5_client = false; } if (reject_des_client || reject_md5_client) { + TALLOC_CTX *frame = talloc_stackframe(); + + if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) { + if (CVE_2022_38023_error_level < DBGLVL_NOTICE) { + CVE_2022_38023_error_level = DBGLVL_NOTICE; + } + DEBUG(CVE_2022_38023_error_level, ( + "CVE-2022-38023: " + "client_account[%s] computer_name[%s] " + "schannel_type[%u] " + "client_negotiate_flags[0x%x] " + "%s%s%s " + "NT_STATUS_DOWNGRADE_DETECTED " + "WEAK_CRYPTO_DISALLOWED\n", + log_escape(frame, r->in.account_name), + log_escape(frame, r->in.computer_name), + r->in.secure_channel_type, + (unsigned)*r->in.negotiate_flags, + trust_account_in_db ? "real_account[" : "", + trust_account_in_db ? trust_account_in_db : "", + trust_account_in_db ? "]" : "")); + goto return_downgrade; + } + + DEBUG(CVE_2022_38023_error_level, ( + "CVE-2022-38023: " + "client_account[%s] computer_name[%s] " + "schannel_type[%u] " + "client_negotiate_flags[0x%x] " + "%s%s%s " + "NT_STATUS_DOWNGRADE_DETECTED " + "reject_des[%u] reject_md5[%u]\n", + log_escape(frame, r->in.account_name), + log_escape(frame, r->in.computer_name), + r->in.secure_channel_type, + (unsigned)*r->in.negotiate_flags, + trust_account_in_db ? "real_account[" : "", + trust_account_in_db ? trust_account_in_db : "", + trust_account_in_db ? "]" : "", + reject_des_client, + reject_md5_client)); + if (trust_account_in_db == NULL) { + goto return_downgrade; + } + + if (reject_md5_client && explicit_md5_opt == NULL) { + DEBUG(CVE_2022_38023_error_level, ( + "CVE-2022-38023: Check if option " + "'server reject md5 schannel:%s = no' " + "might be needed for a legacy client.\n", + trust_account_in_db)); + } + if (reject_des_client && explicit_nt4_opt == NULL) { + DEBUG(CVE_2022_38023_error_level, ( + "CVE-2022-38023: Check if option " + "'allow nt4 crypto:%s = yes' " + "might be needed for a legacy client.\n", + trust_account_in_db)); + } + +return_downgrade: /* * Here we match Windows 2012 and return no flags. */ *r->out.negotiate_flags = 0; + TALLOC_FREE(frame); return NT_STATUS_DOWNGRADE_DETECTED; } @@ -228,6 +323,54 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade( */ *r->out.negotiate_flags = negotiate_flags; + if (!NT_STATUS_IS_OK(orig_status) || trust_account_in_db == NULL) { + return orig_status; + } + + if (global_reject_md5_client && account_reject_md5_client && explicit_md5_opt) { + D_INFO("CVE-2022-38023: Check if option " + "'server reject md5 schannel:%s = yes' not needed!?\n", + trust_account_in_db); + } else if (need_md5 && !account_reject_md5_client && explicit_md5_opt) { + D_INFO("CVE-2022-38023: Check if option " + "'server reject md5 schannel:%s = no' " + "still needed for a legacy client.\n", + trust_account_in_db); + } else if (need_md5 && explicit_md5_opt == NULL) { + DEBUG(CVE_2022_38023_error_level, ( + "CVE-2022-38023: Check if option " + "'server reject md5 schannel:%s = no' " + "might be needed for a legacy client.\n", + trust_account_in_db)); + } else if (!account_reject_md5_client && explicit_md5_opt) { + DEBUG(CVE_2022_38023_warn_level, ( + "CVE-2022-38023: Check if option " + "'server reject md5 schannel:%s = no' not needed!?\n", + trust_account_in_db)); + } + + if (!global_allow_nt4_crypto && !account_allow_nt4_crypto && explicit_nt4_opt) { + D_INFO("CVE-2022-38023: Check if option " + "'allow nt4 crypto:%s = no' not needed!?\n", + trust_account_in_db); + } else if (need_des && account_allow_nt4_crypto && explicit_nt4_opt) { + D_INFO("CVE-2022-38023: Check if option " + "'allow nt4 crypto:%s = yes' " + "still needed for a legacy client.\n", + trust_account_in_db); + } else if (need_des && explicit_nt4_opt == NULL) { + DEBUG(CVE_2022_38023_error_level, ( + "CVE-2022-38023: Check if option " + "'allow nt4 crypto:%s = yes' " + "might be needed for a legacy client.\n", + trust_account_in_db)); + } else if (account_allow_nt4_crypto && explicit_nt4_opt) { + DEBUG(CVE_2022_38023_warn_level, ( + "CVE-2022-38023: Check if option " + "'allow nt4 crypto:%s = yes' not needed!?\n", + trust_account_in_db)); + } + return orig_status; } -- 2.34.1 From a87adec3f25bdbdcec2955ab32f55605d3e472d2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Nov 2022 14:57:20 +0100 Subject: [PATCH 23/30] CVE-2022-38023 selftest:Samba4: avoid global 'allow nt4 crypto = yes' and 'reject md5 clients = no' Instead of using the generic deprecated option use the specific allow nt4 crypto:COMPUTERACCOUNT = yes and server reject md5 schannel:COMPUTERACCOUNT = no in order to allow legacy tests for pass. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 7ae3735810c2db32fa50f309f8af3c76ffa29768) --- selftest/target/Samba4.pm | 60 ++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index d0e5a53d9fb3..3328cf617225 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -1609,7 +1609,6 @@ sub provision_ad_dc_ntvfs($$$) my $extra_conf_options = "netbios aliases = localDC1-a server services = +winbind -winbindd ldap server require strong auth = allow_sasl_over_tls - allow nt4 crypto = yes raw NTLMv2 auth = yes lsa over netlogon = yes rpc server port = 1027 @@ -1621,9 +1620,19 @@ sub provision_ad_dc_ntvfs($$$) client min protocol = CORE server min protocol = LANMAN1 - reject md5 clients = no - CVE_2020_1472:warn_about_unused_debug_level = 3 + CVE_2022_38023:warn_about_unused_debug_level = 3 + allow nt4 crypto:torturetest\$ = yes + server reject md5 schannel:schannel2\$ = no + server reject md5 schannel:schannel3\$ = no + server reject md5 schannel:schannel8\$ = no + server reject md5 schannel:schannel9\$ = no + server reject md5 schannel:torturetest\$ = no + server reject md5 schannel:tests4u2proxywk\$ = no + server reject md5 schannel:tests4u2selfbdc\$ = no + server reject md5 schannel:tests4u2selfwk\$ = no + server reject md5 schannel:torturepacbdc\$ = no + server reject md5 schannel:torturepacwksta\$ = no server require schannel:schannel0\$ = no server require schannel:schannel1\$ = no server require schannel:schannel2\$ = no @@ -1678,6 +1687,13 @@ sub provision_fl2000dc($$) kdc enable fast = no spnego:simulate_w2k=yes ntlmssp_server:force_old_spnego=yes + + CVE_2022_38023:warn_about_unused_debug_level = 3 + server reject md5 schannel:tests4u2proxywk\$ = no + server reject md5 schannel:tests4u2selfbdc\$ = no + server reject md5 schannel:tests4u2selfwk\$ = no + server reject md5 schannel:torturepacbdc\$ = no + server reject md5 schannel:torturepacwksta\$ = no "; my $extra_provision_options = ["--base-schema=2008_R2"]; # This environment uses plain text secrets @@ -1718,11 +1734,23 @@ sub provision_fl2003dc($$$) my $ip_addr2 = Samba::get_ipv6_addr("fakednsforwarder2"); print "PROVISIONING DC WITH FOREST LEVEL 2003...\n"; - my $extra_conf_options = "allow dns updates = nonsecure and secure + my $extra_conf_options = " + allow dns updates = nonsecure and secure + kdc enable fast = no dcesrv:header signing = no dcesrv:max auth states = 0 - dns forwarder = $ip_addr1 [$ip_addr2]:54"; + + dns forwarder = $ip_addr1 [$ip_addr2]:54 + + CVE_2022_38023:warn_about_unused_debug_level = 3 + server reject md5 schannel:tests4u2proxywk\$ = no + server reject md5 schannel:tests4u2selfbdc\$ = no + server reject md5 schannel:tests4u2selfwk\$ = no + server reject md5 schannel:torturepacbdc\$ = no + server reject md5 schannel:torturepacwksta\$ = no +"; + my $extra_provision_options = ["--base-schema=2008_R2"]; my $ret = $self->provision($prefix, "domain controller", @@ -1777,6 +1805,13 @@ sub provision_fl2008r2dc($$$) ldap server require strong auth = no # delay by 10 seconds, 10^7 usecs ldap_server:delay_expire_disconnect = 10000 + + CVE_2022_38023:warn_about_unused_debug_level = 3 + server reject md5 schannel:tests4u2proxywk\$ = no + server reject md5 schannel:tests4u2selfbdc\$ = no + server reject md5 schannel:tests4u2selfwk\$ = no + server reject md5 schannel:torturepacbdc\$ = no + server reject md5 schannel:torturepacwksta\$ = no "; my $extra_provision_options = ["--base-schema=2008_R2"]; my $ret = $self->provision($prefix, @@ -1988,9 +2023,20 @@ sub provision_ad_dc($$$$$$$) lpq cache time = 0 print notify backchannel = yes - reject md5 clients = no - CVE_2020_1472:warn_about_unused_debug_level = 3 + CVE_2022_38023:warn_about_unused_debug_level = 3 + CVE_2022_38023:error_debug_level = 2 + server reject md5 schannel:schannel2\$ = no + server reject md5 schannel:schannel3\$ = no + server reject md5 schannel:schannel8\$ = no + server reject md5 schannel:schannel9\$ = no + server reject md5 schannel:torturetest\$ = no + server reject md5 schannel:tests4u2proxywk\$ = no + server reject md5 schannel:tests4u2selfbdc\$ = no + server reject md5 schannel:tests4u2selfwk\$ = no + server reject md5 schannel:torturepacbdc\$ = no + server reject md5 schannel:torturepacwksta\$ = no + server reject md5 schannel:samlogontest\$ = no server require schannel:schannel0\$ = no server require schannel:schannel1\$ = no server require schannel:schannel2\$ = no -- 2.34.1 From b13741426ca871ccf060b346b33847149af53189 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Nov 2022 16:57:24 +0100 Subject: [PATCH 24/30] CVE-2022-38023 s4:rpc_server/netlogon: split out dcesrv_netr_check_schannel() function This will allow us to reuse the function in other places. As it will also get some additional checks soon. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit f43dc4f0bd60d4e127b714565147f82435aa4f07) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 84 +++++++++++-------- 1 file changed, 51 insertions(+), 33 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index ec5807ef22af..64d75c514f32 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -877,18 +877,11 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_ca return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3); } -/* - * NOTE: The following functions are nearly identical to the ones available in - * source3/rpc_server/srv_nelog_nt.c - * The reason we keep 2 copies is that they use different structures to - * represent the auth_info and the decrpc pipes. - */ -static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call, - TALLOC_CTX *mem_ctx, - const char *computer_name, - struct netr_Authenticator *received_authenticator, - struct netr_Authenticator *return_authenticator, - struct netlogon_creds_CredentialState **creds_out) +static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, + const struct netlogon_creds_CredentialState *creds, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, + uint16_t opnum) { struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; TALLOC_CTX *frame = talloc_stackframe(); @@ -897,15 +890,11 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc bool schannel_global_required = (schannel == true); bool schannel_required = schannel_global_required; const char *explicit_opt = NULL; - struct netlogon_creds_CredentialState *creds = NULL; int CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL, "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR); int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL, "CVE_2020_1472", "error_debug_level", DBGLVL_ERR); unsigned int dbg_lvl = DBGLVL_DEBUG; - enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; - enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; - uint16_t opnum = dce_call->pkt.u.request.opnum; const char *opname = ""; const char *reason = ""; @@ -913,8 +902,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc opname = ndr_table_netlogon.calls[opnum].name; } - dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); - if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { reason = "WITH SEALED"; @@ -927,17 +914,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc reason = "WITHOUT"; } - nt_status = schannel_check_creds_state(mem_ctx, - lp_ctx, - computer_name, - received_authenticator, - return_authenticator, - &creds); - if (!NT_STATUS_IS_OK(nt_status)) { - ZERO_STRUCTP(return_authenticator); - return nt_status; - } - /* * We don't use lpcfg_parm_bool(), as we * need the explicit_opt pointer in order to @@ -977,7 +953,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc log_escape(frame, creds->computer_name))); } - *creds_out = creds; TALLOC_FREE(frame); return nt_status; } @@ -1011,8 +986,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc "might be needed for a legacy client.\n", log_escape(frame, creds->account_name))); } - TALLOC_FREE(creds); - ZERO_STRUCTP(return_authenticator); TALLOC_FREE(frame); return nt_status; } @@ -1056,11 +1029,56 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc log_escape(frame, creds->computer_name))); } - *creds_out = creds; TALLOC_FREE(frame); return NT_STATUS_OK; } +/* + * NOTE: The following functions are nearly identical to the ones available in + * source3/rpc_server/srv_nelog_nt.c + * The reason we keep 2 copies is that they use different structures to + * represent the auth_info and the decrpc pipes. + */ +static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + const char *computer_name, + struct netr_Authenticator *received_authenticator, + struct netr_Authenticator *return_authenticator, + struct netlogon_creds_CredentialState **creds_out) +{ + NTSTATUS nt_status; + struct netlogon_creds_CredentialState *creds = NULL; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + + dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); + + nt_status = schannel_check_creds_state(mem_ctx, + dce_call->conn->dce_ctx->lp_ctx, + computer_name, + received_authenticator, + return_authenticator, + &creds); + if (!NT_STATUS_IS_OK(nt_status)) { + ZERO_STRUCTP(return_authenticator); + return nt_status; + } + + nt_status = dcesrv_netr_check_schannel(dce_call, + creds, + auth_type, + auth_level, + dce_call->pkt.u.request.opnum); + if (!NT_STATUS_IS_OK(nt_status)) { + TALLOC_FREE(creds); + ZERO_STRUCTP(return_authenticator); + return nt_status; + } + + *creds_out = creds; + return NT_STATUS_OK; +} + /* Change the machine account password for the currently connected client. Supplies only the NT#. -- 2.34.1 From 953b8052a1f61fe5cdd81896d0101acf47ead205 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Nov 2022 17:15:36 +0100 Subject: [PATCH 25/30] CVE-2022-38023 s4:rpc_server/netlogon: make sure all dcesrv_netr_LogonSamLogon*() calls go through dcesrv_netr_check_schannel() We'll soon add some additional contraints in dcesrv_netr_check_schannel(), which are also required for dcesrv_netr_LogonSamLogonEx(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 689507457f5e6666488732f91a355a2183fb1662) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 64d75c514f32..a9b16e5c42a3 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -1401,6 +1401,35 @@ static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamL struct auth_usersupplied_info *user_info = NULL; NTSTATUS nt_status; struct tevent_req *subreq = NULL; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + + dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); + + switch (dce_call->pkt.u.request.opnum) { + case NDR_NETR_LOGONSAMLOGON: + case NDR_NETR_LOGONSAMLOGONWITHFLAGS: + /* + * These already called dcesrv_netr_check_schannel() + * via dcesrv_netr_creds_server_step_check() + */ + break; + case NDR_NETR_LOGONSAMLOGONEX: + default: + if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { + return NT_STATUS_ACCESS_DENIED; + } + + nt_status = dcesrv_netr_check_schannel(dce_call, + creds, + auth_type, + auth_level, + dce_call->pkt.u.request.opnum); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + break; + } *r->out.authoritative = 1; @@ -1749,7 +1778,6 @@ static void dcesrv_netr_LogonSamLogon_base_reply( static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct netr_LogonSamLogonEx *r) { - enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; struct dcesrv_netr_LogonSamLogon_base_state *state; NTSTATUS nt_status; @@ -1787,12 +1815,6 @@ static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, return nt_status; } - dcesrv_call_auth_info(dce_call, &auth_type, NULL); - - if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { - return NT_STATUS_ACCESS_DENIED; - } - nt_status = dcesrv_netr_LogonSamLogon_base_call(state); if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) { -- 2.34.1 From fa1144918cac0be0a31fc886ee2fd6c20ce636c4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 25 Nov 2022 16:53:35 +0100 Subject: [PATCH 26/30] CVE-2022-38023 docs-xml/smbdotconf: add "server schannel require seal[:COMPUTERACCOUNT]" options BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 7732a4b0bde1d9f98a0371f17d22648495329470) --- .../smbdotconf/security/serverschannel.xml | 43 ++++++- .../security/serverschannelrequireseal.xml | 118 ++++++++++++++++++ lib/param/loadparm.c | 1 + source3/param/loadparm.c | 1 + 4 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 docs-xml/smbdotconf/security/serverschannelrequireseal.xml diff --git a/docs-xml/smbdotconf/security/serverschannel.xml b/docs-xml/smbdotconf/security/serverschannel.xml index 394ffdc36fbd..5c69f0f64dfb 100644 --- a/docs-xml/smbdotconf/security/serverschannel.xml +++ b/docs-xml/smbdotconf/security/serverschannel.xml @@ -12,19 +12,37 @@ the hardcoded behavior in future). - - Samba will complain in the log files at log level 0, - about the security problem if the option is not set to "yes". + Avoid using this option! Use explicit 'no' instead! + + + Samba will log an error in the log files at log level 0 + if legacy a client is rejected or allowed without an explicit, + 'no' option + for the client. The message will indicate + the explicit 'no' + line to be added, if the legacy client software requires it. (The log level can be adjusted with + '1' + in order to complain only at a higher log level). + + - See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497 + This allows admins to use "auto" only for a short grace period, + in order to collect the explicit + 'no' options. - If you still have legacy domain members use the option. + + See CVE-2020-1472(ZeroLogon), + https://bugzilla.samba.org/show_bug.cgi?id=14497. This option is over-ridden by the option. + This option is over-ridden by the effective value of 'yes' from + the '' + and/or '' options. + yes @@ -48,6 +66,9 @@ about the security problem if the option is not set to "no", but the related computer is actually using the netlogon secure channel (schannel) feature. + (The log level can be adjusted with + '1' + in order to complain only at a higher log level). @@ -56,15 +77,25 @@ - See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497 + See CVE-2020-1472(ZeroLogon), + https://bugzilla.samba.org/show_bug.cgi?id=14497. This option overrides the option. + This option is over-ridden by the effective value of 'yes' from + the '' + and/or '' options. + Which means 'no' + is only useful in combination with 'no' + server require schannel:LEGACYCOMPUTER1$ = no + server require schannel seal:LEGACYCOMPUTER1$ = no server require schannel:NASBOX$ = no + server require schannel seal:NASBOX$ = no server require schannel:LEGACYCOMPUTER2$ = no + server require schannel seal:LEGACYCOMPUTER2$ = no diff --git a/docs-xml/smbdotconf/security/serverschannelrequireseal.xml b/docs-xml/smbdotconf/security/serverschannelrequireseal.xml new file mode 100644 index 000000000000..d4620d1252dd --- /dev/null +++ b/docs-xml/smbdotconf/security/serverschannelrequireseal.xml @@ -0,0 +1,118 @@ + + + + + This option is deprecated and will be removed in future, + as it is a security problem if not set to "yes" (which will be + the hardcoded behavior in future). + + + + This option controls whether the netlogon server (currently + only in 'active directory domain controller' mode), will + reject the usage of netlogon secure channel without privacy/enryption. + + + + The option is modelled after the registry key available on Windows. + + + + HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters\RequireSeal=2 + + + + Avoid using this option! Use the per computer account specific option + '' instead! + Which is available with the patches for + CVE-2022-38023 + see https://bugzilla.samba.org/show_bug.cgi?id=15240. + + + + Samba will log an error in the log files at log level 0 + if legacy a client is rejected or allowed without an explicit, + 'no' option + for the client. The message will indicate + the explicit 'no' + line to be added, if the legacy client software requires it. (The log level can be adjusted with + '1' + in order to complain only at a higher log level). + + + This allows admins to use "no" only for a short grace period, + in order to collect the explicit + 'no' options. + + + When set to 'yes' this option overrides the + '' and + '' options and implies + 'yes'. + + + + This option is over-ridden by the option. + + + + +yes + + + + + + + If you still have legacy domain members, which required "server schannel require seal = no" before, + it is possible to specify explicit exception per computer account + by using 'server schannel require seal:COMPUTERACCOUNT = no' as option. + Note that COMPUTERACCOUNT has to be the sAMAccountName value of + the computer account (including the trailing '$' sign). + + + + Samba will log a complaint in the log files at log level 0 + about the security problem if the option is set to "no", + but the related computer does not require it. + (The log level can be adjusted with + '1' + in order to complain only at a higher log level). + + + + Samba will warn in the log files at log level 5, + if a setting is still needed for the specified computer account. + + + + See CVE-2022-38023, + https://bugzilla.samba.org/show_bug.cgi?id=15240. + + + + This option overrides the '' option. + + + + When set to 'yes' this option overrides the + '' and + '' options and implies + 'yes'. + + + + server require schannel seal:LEGACYCOMPUTER1$ = no + server require schannel seal:NASBOX$ = no + server require schannel seal:LEGACYCOMPUTER2$ = no + + + + diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c index e509cf85bb89..1dcc8061fa21 100644 --- a/lib/param/loadparm.c +++ b/lib/param/loadparm.c @@ -2729,6 +2729,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) lpcfg_do_global_parameter(lp_ctx, "winbind nss info", "template"); lpcfg_do_global_parameter(lp_ctx, "server schannel", "True"); + lpcfg_do_global_parameter(lp_ctx, "server schannel require seal", "True"); lpcfg_do_global_parameter(lp_ctx, "reject md5 clients", "True"); lpcfg_do_global_parameter(lp_ctx, "short preserve case", "True"); diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index c88d241bcf78..9bb5f4cf8cb3 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -668,6 +668,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) Globals.require_strong_key = true; Globals.reject_md5_servers = true; Globals.server_schannel = true; + Globals.server_schannel_require_seal = true; Globals.reject_md5_clients = true; Globals.read_raw = true; Globals.write_raw = true; -- 2.34.1 From a29e855c113c5af16ea9d108c1ee0f869d5f0f3e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 2 Dec 2022 14:31:26 +0100 Subject: [PATCH 27/30] CVE-2022-38023 s4:rpc_server/netlogon: add a per connection cache to dcesrv_netr_check_schannel() It's enough to warn the admin once per connection. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 3c57608e1109c1d6e8bb8fbad2ef0b5d79d00e1a) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 193 ++++++++++++++---- 1 file changed, 153 insertions(+), 40 deletions(-) diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index a9b16e5c42a3..45dcec133fb3 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -877,23 +877,105 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_ca return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3); } -static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, - const struct netlogon_creds_CredentialState *creds, - enum dcerpc_AuthType auth_type, - enum dcerpc_AuthLevel auth_level, - uint16_t opnum) +struct dcesrv_netr_check_schannel_state { + struct dom_sid account_sid; + enum dcerpc_AuthType auth_type; + enum dcerpc_AuthLevel auth_level; + + bool schannel_global_required; + bool schannel_required; + bool schannel_explicitly_set; + + NTSTATUS result; +}; + +static NTSTATUS dcesrv_netr_check_schannel_get_state(struct dcesrv_call_state *dce_call, + const struct netlogon_creds_CredentialState *creds, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, + struct dcesrv_netr_check_schannel_state **_s) { struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; - TALLOC_CTX *frame = talloc_stackframe(); - NTSTATUS nt_status; int schannel = lpcfg_server_schannel(lp_ctx); bool schannel_global_required = (schannel == true); bool schannel_required = schannel_global_required; const char *explicit_opt = NULL; +#define DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC (NETLOGON_SERVER_PIPE_STATE_MAGIC+1) + struct dcesrv_netr_check_schannel_state *s = NULL; + NTSTATUS status; + + *_s = NULL; + + s = dcesrv_iface_state_find_conn(dce_call, + DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC, + struct dcesrv_netr_check_schannel_state); + if (s != NULL) { + if (!dom_sid_equal(&s->account_sid, creds->sid)) { + goto new_state; + } + if (s->auth_type != auth_type) { + goto new_state; + } + if (s->auth_level != auth_level) { + goto new_state; + } + + *_s = s; + return NT_STATUS_OK; + } + +new_state: + TALLOC_FREE(s); + s = talloc_zero(dce_call, + struct dcesrv_netr_check_schannel_state); + if (s == NULL) { + return NT_STATUS_NO_MEMORY; + } + + s->account_sid = *creds->sid; + s->auth_type = auth_type; + s->auth_level = auth_level; + s->result = NT_STATUS_MORE_PROCESSING_REQUIRED; + + /* + * We don't use lpcfg_parm_bool(), as we + * need the explicit_opt pointer in order to + * adjust the debug messages. + */ + explicit_opt = lpcfg_get_parametric(lp_ctx, + NULL, + "server require schannel", + creds->account_name); + if (explicit_opt != NULL) { + schannel_required = lp_bool(explicit_opt); + } + + s->schannel_global_required = schannel_global_required; + s->schannel_required = schannel_required; + s->schannel_explicitly_set = explicit_opt != NULL; + + status = dcesrv_iface_state_store_conn(dce_call, + DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC, + s); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + *_s = s; + return NT_STATUS_OK; +} + +static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_call, + struct dcesrv_netr_check_schannel_state *s, + const struct netlogon_creds_CredentialState *creds, + uint16_t opnum) +{ + struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; int CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL, "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR); int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL, "CVE_2020_1472", "error_debug_level", DBGLVL_ERR); + TALLOC_CTX *frame = talloc_stackframe(); unsigned int dbg_lvl = DBGLVL_DEBUG; const char *opname = ""; const char *reason = ""; @@ -902,37 +984,43 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, opname = ndr_table_netlogon.calls[opnum].name; } - if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { - if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { + if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + if (s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { reason = "WITH SEALED"; - } else if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) { + } else if (s->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) { reason = "WITH SIGNED"; } else { - smb_panic("Schannel without SIGN/SEAL"); + reason = "WITH INVALID"; + dbg_lvl = DBGLVL_ERR; + s->result = NT_STATUS_INTERNAL_ERROR; } } else { reason = "WITHOUT"; } - /* - * We don't use lpcfg_parm_bool(), as we - * need the explicit_opt pointer in order to - * adjust the debug messages. - */ - explicit_opt = lpcfg_get_parametric(lp_ctx, - NULL, - "server require schannel", - creds->account_name); - if (explicit_opt != NULL) { - schannel_required = lp_bool(explicit_opt); + if (!NT_STATUS_EQUAL(s->result, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + if (!NT_STATUS_IS_OK(s->result)) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); + } + + DEBUG(dbg_lvl, ( + "CVE-2020-1472(ZeroLogon): " + "%s request (opnum[%u]) %s schannel from " + "client_account[%s] client_computer_name[%s] %s\n", + opname, opnum, reason, + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name), + nt_errstr(s->result))); + TALLOC_FREE(frame); + return s->result; } - if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { - nt_status = NT_STATUS_OK; + if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + s->result = NT_STATUS_OK; - if (explicit_opt != NULL && !schannel_required) { + if (s->schannel_explicitly_set && !s->schannel_required) { dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level); - } else if (!schannel_required) { + } else if (!s->schannel_required) { dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); } @@ -943,9 +1031,8 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, opname, opnum, reason, log_escape(frame, creds->account_name), log_escape(frame, creds->computer_name), - nt_errstr(nt_status))); - - if (explicit_opt != NULL && !schannel_required) { + nt_errstr(s->result))); + if (s->schannel_explicitly_set && !s->schannel_required) { DEBUG(CVE_2020_1472_warn_level, ( "CVE-2020-1472(ZeroLogon): " "Option 'server require schannel:%s = no' not needed for '%s'!\n", @@ -954,13 +1041,13 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, } TALLOC_FREE(frame); - return nt_status; + return s->result; } - if (schannel_required) { - nt_status = NT_STATUS_ACCESS_DENIED; + if (s->schannel_required) { + s->result = NT_STATUS_ACCESS_DENIED; - if (explicit_opt != NULL) { + if (s->schannel_explicitly_set) { dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); } else { dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); @@ -973,8 +1060,8 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, opname, opnum, reason, log_escape(frame, creds->account_name), log_escape(frame, creds->computer_name), - nt_errstr(nt_status))); - if (explicit_opt != NULL) { + nt_errstr(s->result))); + if (s->schannel_explicitly_set) { D_NOTICE("CVE-2020-1472(ZeroLogon): Option " "'server require schannel:%s = yes' " "rejects access for client.\n", @@ -987,12 +1074,12 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, log_escape(frame, creds->account_name))); } TALLOC_FREE(frame); - return nt_status; + return s->result; } - nt_status = NT_STATUS_OK; + s->result = NT_STATUS_OK; - if (explicit_opt != NULL) { + if (s->schannel_explicitly_set) { dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); } else { dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); @@ -1005,9 +1092,9 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, opname, opnum, reason, log_escape(frame, creds->account_name), log_escape(frame, creds->computer_name), - nt_errstr(nt_status))); + nt_errstr(s->result))); - if (explicit_opt != NULL) { + if (s->schannel_explicitly_set) { D_INFO("CVE-2020-1472(ZeroLogon): Option " "'server require schannel:%s = no' " "still needed for '%s'!\n", @@ -1030,6 +1117,32 @@ static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, } TALLOC_FREE(frame); + return s->result; +} + +static NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, + const struct netlogon_creds_CredentialState *creds, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, + uint16_t opnum) +{ + struct dcesrv_netr_check_schannel_state *s = NULL; + NTSTATUS status; + + status = dcesrv_netr_check_schannel_get_state(dce_call, + creds, + auth_type, + auth_level, + &s); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = dcesrv_netr_check_schannel_once(dce_call, s, creds, opnum); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + return NT_STATUS_OK; } -- 2.34.1 From a19b425cccd935c77cf15f3123ed2611fc30cea6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 25 Nov 2022 14:05:30 +0100 Subject: [PATCH 28/30] CVE-2022-38023 s4:rpc_server/netlogon: implement "server schannel require seal[:COMPUTERACCOUNT]" By default we'll now require schannel connections with privacy/sealing/encryption. But we allow exceptions for specific computer/trust accounts. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit b3ed90a0541a271a7c6d4bee1201fa47adc3c0c1) --- selftest/target/Samba4.pm | 28 ++ source4/rpc_server/netlogon/dcerpc_netlogon.c | 244 +++++++++++++++++- 2 files changed, 271 insertions(+), 1 deletion(-) diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 3328cf617225..5c83bcbd4038 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -1646,9 +1646,23 @@ sub provision_ad_dc_ntvfs($$$) server require schannel:schannel10\$ = no server require schannel:schannel11\$ = no server require schannel:torturetest\$ = no + server schannel require seal:schannel0\$ = no + server schannel require seal:schannel1\$ = no + server schannel require seal:schannel2\$ = no + server schannel require seal:schannel3\$ = no + server schannel require seal:schannel4\$ = no + server schannel require seal:schannel5\$ = no + server schannel require seal:schannel6\$ = no + server schannel require seal:schannel7\$ = no + server schannel require seal:schannel8\$ = no + server schannel require seal:schannel9\$ = no + server schannel require seal:schannel10\$ = no + server schannel require seal:schannel11\$ = no + server schannel require seal:torturetest\$ = no # needed for 'samba.tests.auth_log' tests server require schannel:LOCALDC\$ = no + server schannel require seal:LOCALDC\$ = no "; push (@{$extra_provision_options}, "--use-ntvfs"); my $ret = $self->provision($prefix, @@ -2050,6 +2064,19 @@ sub provision_ad_dc($$$$$$$) server require schannel:schannel10\$ = no server require schannel:schannel11\$ = no server require schannel:torturetest\$ = no + server schannel require seal:schannel0\$ = no + server schannel require seal:schannel1\$ = no + server schannel require seal:schannel2\$ = no + server schannel require seal:schannel3\$ = no + server schannel require seal:schannel4\$ = no + server schannel require seal:schannel5\$ = no + server schannel require seal:schannel6\$ = no + server schannel require seal:schannel7\$ = no + server schannel require seal:schannel8\$ = no + server schannel require seal:schannel9\$ = no + server schannel require seal:schannel10\$ = no + server schannel require seal:schannel11\$ = no + server schannel require seal:torturetest\$ = no auth event notification = true dsdb event notification = true @@ -2743,6 +2770,7 @@ sub setup_ad_dc_smb1 # needed for 'samba.tests.auth_log' tests server require schannel:ADDCSMB1\$ = no + server schannel require seal:ADDCSMB1\$ = no "; return _setup_ad_dc($self, $path, $conf_opts, "addcsmb1", "addom2.samba.example.com"); } diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 45dcec133fb3..aa24a539abfd 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -68,9 +68,11 @@ static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx); int schannel = lpcfg_server_schannel(lp_ctx); bool schannel_global_required = (schannel == true); + bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx); static bool warned_global_nt4_once = false; static bool warned_global_md5_once = false; static bool warned_global_schannel_once = false; + static bool warned_global_seal_once = false; if (global_allow_nt4_crypto && !warned_global_nt4_once) { /* @@ -102,6 +104,16 @@ static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context warned_global_schannel_once = true; } + if (!global_require_seal && !warned_global_seal_once) { + /* + * We want admins to notice their misconfiguration! + */ + D_ERR("CVE-2022-38023 (and others): " + "Please configure 'server schannel require seal = yes' (the default), " + "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n"); + warned_global_seal_once = true; + } + return dcesrv_interface_bind_reject_connect(context, iface); } @@ -886,6 +898,10 @@ struct dcesrv_netr_check_schannel_state { bool schannel_required; bool schannel_explicitly_set; + bool seal_global_required; + bool seal_required; + bool seal_explicitly_set; + NTSTATUS result; }; @@ -900,6 +916,9 @@ static NTSTATUS dcesrv_netr_check_schannel_get_state(struct dcesrv_call_state *d bool schannel_global_required = (schannel == true); bool schannel_required = schannel_global_required; const char *explicit_opt = NULL; + bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx); + bool require_seal = global_require_seal; + const char *explicit_seal_opt = NULL; #define DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC (NETLOGON_SERVER_PIPE_STATE_MAGIC+1) struct dcesrv_netr_check_schannel_state *s = NULL; NTSTATUS status; @@ -937,6 +956,19 @@ new_state: s->auth_level = auth_level; s->result = NT_STATUS_MORE_PROCESSING_REQUIRED; + /* + * We don't use lpcfg_parm_bool(), as we + * need the explicit_opt pointer in order to + * adjust the debug messages. + */ + explicit_seal_opt = lpcfg_get_parametric(lp_ctx, + NULL, + "server schannel require seal", + creds->account_name); + if (explicit_seal_opt != NULL) { + require_seal = lp_bool(explicit_seal_opt); + } + /* * We don't use lpcfg_parm_bool(), as we * need the explicit_opt pointer in order to @@ -954,6 +986,10 @@ new_state: s->schannel_required = schannel_required; s->schannel_explicitly_set = explicit_opt != NULL; + s->seal_global_required = global_require_seal; + s->seal_required = require_seal; + s->seal_explicitly_set = explicit_seal_opt != NULL; + status = dcesrv_iface_state_store_conn(dce_call, DCESRV_NETR_CHECK_SCHANNEL_STATE_MAGIC, s); @@ -975,6 +1011,10 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR); int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL, "CVE_2020_1472", "error_debug_level", DBGLVL_ERR); + int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL, + "CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR); + int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL, + "CVE_2022_38023", "error_debug_level", DBGLVL_ERR); TALLOC_CTX *frame = talloc_stackframe(); unsigned int dbg_lvl = DBGLVL_DEBUG; const char *opname = ""; @@ -1004,18 +1044,107 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca } DEBUG(dbg_lvl, ( - "CVE-2020-1472(ZeroLogon): " + "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " + "%s request (opnum[%u]) %s schannel from " + "client_account[%s] client_computer_name[%s] %s\n", + opname, opnum, reason, + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name), + nt_errstr(s->result))); + TALLOC_FREE(frame); + return s->result; + } + + if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL && + s->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) + { + s->result = NT_STATUS_OK; + + if (s->schannel_explicitly_set && !s->schannel_required) { + dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_warn_level); + } else if (!s->schannel_required) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); + } + if (s->seal_explicitly_set && !s->seal_required) { + dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_warn_level); + } else if (!s->seal_required) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); + } + + DEBUG(dbg_lvl, ( + "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " "%s request (opnum[%u]) %s schannel from " "client_account[%s] client_computer_name[%s] %s\n", opname, opnum, reason, log_escape(frame, creds->account_name), log_escape(frame, creds->computer_name), nt_errstr(s->result))); + + if (s->schannel_explicitly_set && !s->schannel_required) { + DEBUG(CVE_2020_1472_warn_level, ( + "CVE-2020-1472(ZeroLogon): " + "Option 'server require schannel:%s = no' not needed for '%s'!\n", + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name))); + } + + if (s->seal_explicitly_set && !s->seal_required) { + DEBUG(CVE_2022_38023_warn_level, ( + "CVE-2022-38023: " + "Option 'server schannel require seal:%s = no' not needed for '%s'!\n", + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name))); + } + TALLOC_FREE(frame); return s->result; } if (s->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + if (s->seal_required) { + s->result = NT_STATUS_ACCESS_DENIED; + + if (s->seal_explicitly_set) { + dbg_lvl = DBGLVL_NOTICE; + } else { + dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); + } + if (s->schannel_explicitly_set && !s->schannel_required) { + dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_warn_level); + } + + DEBUG(dbg_lvl, ( + "CVE-2022-38023: " + "%s request (opnum[%u]) %s schannel from " + "from client_account[%s] client_computer_name[%s] %s\n", + opname, opnum, reason, + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name), + nt_errstr(s->result))); + if (s->seal_explicitly_set) { + D_NOTICE("CVE-2022-38023: Option " + "'server schannel require seal:%s = yes' " + "rejects access for client.\n", + log_escape(frame, creds->account_name)); + } else { + DEBUG(CVE_2020_1472_error_level, ( + "CVE-2022-38023: Check if option " + "'server schannel require seal:%s = no' " + "might be needed for a legacy client.\n", + log_escape(frame, creds->account_name))); + } + if (s->schannel_explicitly_set && !s->schannel_required) { + DEBUG(CVE_2020_1472_warn_level, ( + "CVE-2020-1472(ZeroLogon): Option " + "'server require schannel:%s = no' " + "not needed for '%s'!\n", + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name))); + } + TALLOC_FREE(frame); + return s->result; + } + s->result = NT_STATUS_OK; if (s->schannel_explicitly_set && !s->schannel_required) { @@ -1023,6 +1152,11 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca } else if (!s->schannel_required) { dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); } + if (s->seal_explicitly_set && !s->seal_required) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); + } else if (!s->seal_required) { + dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); + } DEBUG(dbg_lvl, ( "CVE-2020-1472(ZeroLogon): " @@ -1039,7 +1173,77 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca log_escape(frame, creds->account_name), log_escape(frame, creds->computer_name))); } + if (s->seal_explicitly_set && !s->seal_required) { + D_INFO("CVE-2022-38023: " + "Option 'server schannel require seal:%s = no' still needed for '%s'!\n", + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name)); + } else if (!s->seal_required) { + /* + * admins should set + * server schannel require seal:COMPUTER$ = no + * in order to avoid the level 0 messages. + * Over time they can switch the global value + * to be strict. + */ + DEBUG(CVE_2022_38023_error_level, ( + "CVE-2022-38023: " + "Please use 'server schannel require seal:%s = no' " + "for '%s' to avoid this warning!\n", + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name))); + } + + TALLOC_FREE(frame); + return s->result; + } + + if (s->seal_required) { + s->result = NT_STATUS_ACCESS_DENIED; + + if (s->seal_explicitly_set) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); + } else { + dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); + } + if (!s->schannel_explicitly_set) { + dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); + } else if (s->schannel_required) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_NOTICE); + } + DEBUG(dbg_lvl, ( + "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " + "%s request (opnum[%u]) %s schannel from " + "from client_account[%s] client_computer_name[%s] %s\n", + opname, opnum, reason, + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name), + nt_errstr(s->result))); + if (s->seal_explicitly_set) { + D_NOTICE("CVE-2022-38023: Option " + "'server schannel require seal:%s = yes' " + "rejects access for client.\n", + log_escape(frame, creds->account_name)); + } else { + DEBUG(CVE_2022_38023_error_level, ( + "CVE-2022-38023: Check if option " + "'server schannel require seal:%s = no' " + "might be needed for a legacy client.\n", + log_escape(frame, creds->account_name))); + } + if (!s->schannel_explicitly_set) { + DEBUG(CVE_2020_1472_error_level, ( + "CVE-2020-1472(ZeroLogon): Check if option " + "'server require schannel:%s = no' " + "might be needed for a legacy client.\n", + log_escape(frame, creds->account_name))); + } else if (s->schannel_required) { + D_NOTICE("CVE-2022-38023: Option " + "'server require schannel:%s = yes' " + "also rejects access for client.\n", + log_escape(frame, creds->account_name)); + } TALLOC_FREE(frame); return s->result; } @@ -1052,6 +1256,9 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca } else { dbg_lvl = MIN(dbg_lvl, CVE_2020_1472_error_level); } + if (!s->seal_explicitly_set) { + dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); + } DEBUG(dbg_lvl, ( "CVE-2020-1472(ZeroLogon)/CVE-2022-38023: " @@ -1073,12 +1280,25 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca "might be needed for a legacy client.\n", log_escape(frame, creds->account_name))); } + if (!s->seal_explicitly_set) { + DEBUG(CVE_2022_38023_error_level, ( + "CVE-2022-38023: Check if option " + "'server schannel require seal:%s = no' " + "might be needed for a legacy client.\n", + log_escape(frame, creds->account_name))); + } TALLOC_FREE(frame); return s->result; } s->result = NT_STATUS_OK; + if (s->seal_explicitly_set) { + dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); + } else { + dbg_lvl = MIN(dbg_lvl, CVE_2022_38023_error_level); + } + if (s->schannel_explicitly_set) { dbg_lvl = MIN(dbg_lvl, DBGLVL_INFO); } else { @@ -1094,6 +1314,28 @@ static NTSTATUS dcesrv_netr_check_schannel_once(struct dcesrv_call_state *dce_ca log_escape(frame, creds->computer_name), nt_errstr(s->result))); + if (s->seal_explicitly_set) { + D_INFO("CVE-2022-38023: Option " + "'server schannel require seal:%s = no' " + "still needed for '%s'!\n", + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name)); + } else { + /* + * admins should set + * server schannel require seal:COMPUTER$ = no + * in order to avoid the level 0 messages. + * Over time they can switch the global value + * to be strict. + */ + DEBUG(CVE_2022_38023_error_level, ( + "CVE-2022-38023: Please use " + "'server schannel require seal:%s = no' " + "for '%s' to avoid this warning!\n", + log_escape(frame, creds->account_name), + log_escape(frame, creds->computer_name))); + } + if (s->schannel_explicitly_set) { D_INFO("CVE-2020-1472(ZeroLogon): Option " "'server require schannel:%s = no' " -- 2.34.1 From 8ec894c5b4ebe4438cd5b7582ac436ce464188bd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 30 Nov 2022 15:13:47 +0100 Subject: [PATCH 29/30] CVE-2022-38023 testparm: warn about server/client schannel != yes BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit f964c0c357214637f80d0089723b9b11d1b38f7e) --- source3/utils/testparm.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c index e0455b9d7b6b..7e913a8ac4d3 100644 --- a/source3/utils/testparm.c +++ b/source3/utils/testparm.c @@ -598,11 +598,25 @@ static int do_global_checks(void) ret = 1; } - if (!lp_server_schannel()) { + if (lp_server_schannel() != true) { /* can be 'auto' */ fprintf(stderr, - "WARNING: You have configured 'server schannel = no'. " + "WARNING: You have not configured " + "'server schannel = yes' (the default). " "Your server is vulernable to \"ZeroLogon\" " - "(CVE-2020-1472)\n\n"); + "(CVE-2020-1472)\n" + "If required use individual " + "'server require schannel:COMPUTERACCOUNT$ = no' " + "options\n\n"); + } + if (lp_client_schannel() != true) { /* can be 'auto' */ + fprintf(stderr, + "WARNING: You have not configured " + "'client schannel = yes' (the default). " + "Your server is vulernable to \"ZeroLogon\" " + "(CVE-2020-1472)\n" + "If required use individual " + "'client schannel:NETBIOSDOMAIN = no' " + "options\n\n"); } return ret; -- 2.34.1 From 6a9ac02107834bc102020dea77483f66d87fe422 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Dec 2022 13:36:17 +0100 Subject: [PATCH 30/30] CVE-2022-38023 testparm: warn about unsecure schannel related options BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett Reviewed-by: Ralph Boehme (cherry picked from commit 4d540473c3d43d048a30dd63efaeae9ff87b2aeb) --- source3/utils/testparm.c | 61 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c index 7e913a8ac4d3..121c2b7a5221 100644 --- a/source3/utils/testparm.c +++ b/source3/utils/testparm.c @@ -608,6 +608,37 @@ static int do_global_checks(void) "'server require schannel:COMPUTERACCOUNT$ = no' " "options\n\n"); } + if (lp_allow_nt4_crypto()) { + fprintf(stderr, + "WARNING: You have not configured " + "'allow nt4 crypto = no' (the default). " + "Your server is vulernable to " + "CVE-2022-38023 and others!\n" + "If required use individual " + "'allow nt4 crypto:COMPUTERACCOUNT$ = yes' " + "options\n\n"); + } + if (!lp_reject_md5_clients()) { + fprintf(stderr, + "WARNING: You have not configured " + "'reject md5 clients = yes' (the default). " + "Your server is vulernable to " + "CVE-2022-38023!\n" + "If required use individual " + "'server reject md5 schannel:COMPUTERACCOUNT$ = yes' " + "options\n\n"); + } + if (!lp_server_schannel_require_seal()) { + fprintf(stderr, + "WARNING: You have not configured " + "'server schannel require seal = yes' (the default). " + "Your server is vulernable to " + "CVE-2022-38023!\n" + "If required use individual " + "'server schannel require seal:COMPUTERACCOUNT$ = no' " + "options\n\n"); + } + if (lp_client_schannel() != true) { /* can be 'auto' */ fprintf(stderr, "WARNING: You have not configured " @@ -618,6 +649,36 @@ static int do_global_checks(void) "'client schannel:NETBIOSDOMAIN = no' " "options\n\n"); } + if (!lp_reject_md5_servers()) { + fprintf(stderr, + "WARNING: You have not configured " + "'reject md5 servers = yes' (the default). " + "Your server is vulernable to " + "CVE-2022-38023\n" + "If required use individual " + "'reject md5 servers:NETBIOSDOMAIN = no' " + "options\n\n"); + } + if (!lp_require_strong_key()) { + fprintf(stderr, + "WARNING: You have not configured " + "'require strong key = yes' (the default). " + "Your server is vulernable to " + "CVE-2022-38023\n" + "If required use individual " + "'require strong key:NETBIOSDOMAIN = no' " + "options\n\n"); + } + if (!lp_winbind_sealed_pipes()) { + fprintf(stderr, + "WARNING: You have not configured " + "'winbind sealed pipes = yes' (the default). " + "Your server is vulernable to " + "CVE-2022-38023\n" + "If required use individual " + "'winbind sealed pipes:NETBIOSDOMAIN = no' " + "options\n\n"); + } return ret; } -- 2.34.1