diff -Nru samba-4.11.6+dfsg/debian/changelog samba-4.11.6+dfsg/debian/changelog --- samba-4.11.6+dfsg/debian/changelog 2020-08-07 17:31:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/changelog 2020-09-18 16:33:05.000000000 +0000 @@ -1,3 +1,19 @@ +samba (2:4.11.6+dfsg-0ubuntu1.5) focal-security; urgency=medium + + * SECURITY UPDATE: Unauthenticated domain controller compromise by + subverting Netlogon cryptography (ZeroLogon) + - debian/patches/zerologon-*.patch: backport upstream patches: + + For compatibility reasons, allow specifying an insecure netlogon + configuration per machine. See the following link for examples: + https://www.samba.org/samba/security/CVE-2020-1472.html + + Add additional server checks for the protocol attack in the + client-specified challenge to provide some protection when + 'server schannel = no/auto' and avoid the false-positive results + when running the proof-of-concept exploit. + - CVE-2020-1472 + + -- Marc Deslauriers Fri, 18 Sep 2020 12:33:05 -0400 + samba (2:4.11.6+dfsg-0ubuntu1.4) focal-security; urgency=medium * SECURITY UPDATE: Empty UDP packet DoS in Samba AD DC nbtd diff -Nru samba-4.11.6+dfsg/debian/patches/series samba-4.11.6+dfsg/debian/patches/series --- samba-4.11.6+dfsg/debian/patches/series 2020-08-07 17:30:55.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/series 2020-09-18 16:32:55.000000000 +0000 @@ -40,3 +40,22 @@ CVE-2020-10760-1.patch CVE-2020-10760-2.patch CVE-2020-14303.patch +zerologon-1.patch +zerologon-2.patch +zerologon-3.patch +zerologon-4.patch +zerologon-5.patch +zerologon-6.patch +zerologon-7.patch +zerologon-8.patch +zerologon-9.patch +zerologon-10.patch +zerologon-11.patch +zerologon-12.patch +zerologon-13.patch +zerologon-14.patch +zerologon-15.patch +zerologon-16.patch +zerologon-17.patch +zerologon-18.patch +zerologon-19.patch diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-10.patch samba-4.11.6+dfsg/debian/patches/zerologon-10.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-10.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-10.patch 2020-09-18 16:32:23.000000000 +0000 @@ -0,0 +1,144 @@ +From 0da2f3e2455999cc30761a40715a1f1a88e1b725 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Wed, 16 Sep 2020 12:53:50 -0700 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: protect + netr_ServerPasswordSet2 against unencrypted passwords + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Pair-Programmed-With: Stefan Metzmacher + +Signed-off-by: Jeremy Allison +Signed-off-by: Stefan Metzmacher +--- + source3/rpc_server/netlogon/srv_netlog_nt.c | 98 +++++++++++++++++++-- + 1 file changed, 92 insertions(+), 6 deletions(-) + +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index bc5ec654a95..3ffdde34142 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -1325,9 +1325,14 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, + { + NTSTATUS status; + struct netlogon_creds_CredentialState *creds = NULL; +- DATA_BLOB plaintext; ++ DATA_BLOB plaintext = data_blob_null; ++ DATA_BLOB new_password = data_blob_null; ++ size_t confounder_len; ++ DATA_BLOB dec_blob = data_blob_null; ++ DATA_BLOB enc_blob = data_blob_null; + struct samr_CryptPassword password_buf; + struct _samr_Credentials_t cr = { CRED_TYPE_PLAIN_TEXT, {0}}; ++ bool ok; + + become_root(); + status = netr_creds_server_step_check(p, p->mem_ctx, +@@ -1369,18 +1374,99 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, + } + } + +- if (!decode_pw_buffer(p->mem_ctx, +- password_buf.data, +- (char**) &plaintext.data, +- &plaintext.length, +- CH_UTF16)) { ++ if (!extract_pw_from_buffer(p->mem_ctx, password_buf.data, &new_password)) { + DEBUG(2,("_netr_ServerPasswordSet2: unable to extract password " + "from a buffer. Rejecting auth request as a wrong password\n")); + TALLOC_FREE(creds); + return NT_STATUS_WRONG_PASSWORD; + } + ++ /* ++ * Make sure the length field was encrypted, ++ * otherwise we are under attack. ++ */ ++ if (new_password.length == r->in.new_password->length) { ++ DBG_WARNING("Length[%zu] field not encrypted\n", ++ new_password.length); ++ TALLOC_FREE(creds); ++ return NT_STATUS_WRONG_PASSWORD; ++ } ++ ++ /* ++ * We don't allow empty passwords for machine accounts. ++ */ ++ if (new_password.length < 2) { ++ DBG_WARNING("Empty password Length[%zu]\n", ++ new_password.length); ++ TALLOC_FREE(creds); ++ return NT_STATUS_WRONG_PASSWORD; ++ } ++ ++ /* ++ * Make sure the confounder part of CryptPassword ++ * buffer was encrypted, otherwise we are under attack. ++ */ ++ confounder_len = 512 - new_password.length; ++ enc_blob = data_blob_const(r->in.new_password->data, confounder_len); ++ dec_blob = data_blob_const(password_buf.data, confounder_len); ++ if (data_blob_cmp(&dec_blob, &enc_blob) == 0) { ++ DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n", ++ confounder_len); ++ TALLOC_FREE(creds); ++ return NT_STATUS_WRONG_PASSWORD; ++ } ++ ++ /* ++ * Check that the password part was actually encrypted, ++ * otherwise we are under attack. ++ */ ++ enc_blob = data_blob_const(r->in.new_password->data + confounder_len, ++ new_password.length); ++ dec_blob = data_blob_const(password_buf.data + confounder_len, ++ new_password.length); ++ if (data_blob_cmp(&dec_blob, &enc_blob) == 0) { ++ DBG_WARNING("Password buffer not encrypted Length[%zu]\n", ++ new_password.length); ++ TALLOC_FREE(creds); ++ return NT_STATUS_WRONG_PASSWORD; ++ } ++ ++ /* ++ * don't allow zero buffers ++ */ ++ if (all_zero(new_password.data, new_password.length)) { ++ DBG_WARNING("Password zero buffer Length[%zu]\n", ++ new_password.length); ++ TALLOC_FREE(creds); ++ return NT_STATUS_WRONG_PASSWORD; ++ } ++ ++ /* Convert from UTF16 -> plaintext. */ ++ ok = convert_string_talloc(p->mem_ctx, ++ CH_UTF16, ++ CH_UNIX, ++ new_password.data, ++ new_password.length, ++ (void *)&plaintext.data, ++ &plaintext.length); ++ if (!ok) { ++ DBG_WARNING("unable to extract password from a buffer. " ++ "Rejecting auth request as a wrong password\n"); ++ TALLOC_FREE(creds); ++ return NT_STATUS_WRONG_PASSWORD; ++ } ++ ++ /* ++ * We don't allow empty passwords for machine accounts. ++ */ ++ + cr.creds.password = (const char*) plaintext.data; ++ if (strlen(cr.creds.password) == 0) { ++ DBG_WARNING("Empty plaintext password\n"); ++ TALLOC_FREE(creds); ++ return NT_STATUS_WRONG_PASSWORD; ++ } ++ + status = netr_set_machine_account_password(p->mem_ctx, + p->session_info, + p->msg_ctx, +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-11.patch samba-4.11.6+dfsg/debian/patches/zerologon-11.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-11.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-11.patch 2020-09-18 16:32:26.000000000 +0000 @@ -0,0 +1,82 @@ +From f867164dc57b85c3c69b08be51c64aa430a23b2e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 10:18:45 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon: refactor + dcesrv_netr_creds_server_step_check() + +We should debug more details about the failing request. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Stefan Metzmacher +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 45 ++++++++++++++----- + 1 file changed, 33 insertions(+), 12 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index a8d8d95130f..afc0687b882 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -622,26 +622,47 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + NTSTATUS nt_status; + int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx); + bool schannel_global_required = (schannel == true); ++ struct netlogon_creds_CredentialState *creds = NULL; ++ enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; ++ uint16_t opnum = dce_call->pkt.u.request.opnum; ++ const char *opname = ""; + +- if (schannel_global_required) { +- enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; +- +- dcesrv_call_auth_info(dce_call, &auth_type, NULL); +- +- if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { +- DBG_ERR("[%s] is not using schannel\n", +- computer_name); +- return NT_STATUS_ACCESS_DENIED; +- } ++ if (opnum < ndr_table_netlogon.num_calls) { ++ opname = ndr_table_netlogon.calls[opnum].name; + } + ++ dcesrv_call_auth_info(dce_call, &auth_type, NULL); ++ + nt_status = schannel_check_creds_state(mem_ctx, + dce_call->conn->dce_ctx->lp_ctx, + computer_name, + received_authenticator, + return_authenticator, +- creds_out); +- return nt_status; ++ &creds); ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ ZERO_STRUCTP(return_authenticator); ++ return nt_status; ++ } ++ ++ if (schannel_global_required) { ++ if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { ++ *creds_out = creds; ++ return NT_STATUS_OK; ++ } ++ ++ 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)); ++ TALLOC_FREE(creds); ++ ZERO_STRUCTP(return_authenticator); ++ return NT_STATUS_ACCESS_DENIED; ++ } ++ ++ *creds_out = creds; ++ return NT_STATUS_OK; + } + + /* +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-12.patch samba-4.11.6+dfsg/debian/patches/zerologon-12.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-12.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-12.patch 2020-09-18 16:32:30.000000000 +0000 @@ -0,0 +1,46 @@ +From 92d7e9f7f92f1ff225cd52fb24242a0f5d8f1d3d Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 10:56:53 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon: support + "server require schannel:WORKSTATION$ = no" + +This allows to add expections for individual workstations, when using "server schannel = yes". +"server schannel = auto" is very insecure and will be removed soon. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Stefan Metzmacher +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index afc0687b882..051513adc08 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -622,6 +622,7 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + NTSTATUS nt_status; + int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx); + bool schannel_global_required = (schannel == true); ++ bool schannel_required = schannel_global_required; + struct netlogon_creds_CredentialState *creds = NULL; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + uint16_t opnum = dce_call->pkt.u.request.opnum; +@@ -644,7 +645,13 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + return nt_status; + } + +- if (schannel_global_required) { ++ schannel_required = lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx, ++ NULL, ++ "server require schannel", ++ creds->account_name, ++ schannel_global_required); ++ ++ if (schannel_required) { + if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + *creds_out = creds; + return NT_STATUS_OK; +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-13.patch samba-4.11.6+dfsg/debian/patches/zerologon-13.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-13.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-13.patch 2020-09-18 16:32:33.000000000 +0000 @@ -0,0 +1,126 @@ +From c836fc24b9c11752581ac9d314ecdde80588aba2 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 17 Sep 2020 13:37:26 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon: log + warnings about unsecure configurations +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +This should give admins wawrnings until they have a secure +configuration. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Ralph Boehme +Reviewed-by: Günther Deschner +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 66 ++++++++++++++++++- + 1 file changed, 63 insertions(+), 3 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index 051513adc08..63e2821cac7 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -623,10 +623,12 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + int schannel = lpcfg_server_schannel(dce_call->conn->dce_ctx->lp_ctx); + bool schannel_global_required = (schannel == true); + bool schannel_required = schannel_global_required; ++ const char *explicit_opt = NULL; + struct netlogon_creds_CredentialState *creds = NULL; + 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; +@@ -645,11 +647,18 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + return nt_status; + } + +- schannel_required = lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx, ++ /* ++ * 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(dce_call->conn->dce_ctx->lp_ctx, + NULL, + "server require schannel", +- creds->account_name, +- schannel_global_required); ++ creds->account_name); ++ if (explicit_opt != NULL) { ++ schannel_required = lp_bool(explicit_opt); ++ } + + if (schannel_required) { + if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { +@@ -663,11 +672,62 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc + opname, opnum, + log_escape(mem_ctx, creds->account_name), + log_escape(mem_ctx, 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)); + TALLOC_FREE(creds); + ZERO_STRUCTP(return_authenticator); + 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 " ++ "client_account[%s] client_computer_name[%s]\n", ++ opname, opnum, ++ log_escape(mem_ctx, creds->account_name), ++ log_escape(mem_ctx, 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)); ++ ++ *creds_out = creds; ++ return 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(mem_ctx, creds->account_name), ++ log_escape(mem_ctx, 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)); ++ } 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)); ++ 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)); ++ } ++ + *creds_out = creds; + return NT_STATUS_OK; + } +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-14.patch samba-4.11.6+dfsg/debian/patches/zerologon-14.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-14.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-14.patch 2020-09-18 16:32:36.000000000 +0000 @@ -0,0 +1,100 @@ +From 5ee9480a89860d6906710fac39067e7d9db14feb Mon Sep 17 00:00:00 2001 +From: =?utf8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 17 Sep 2020 14:57:22 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: refactor + dcesrv_netr_creds_server_step_check() +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +We should debug more details about the failing request. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Pair-Programmed-With: Stefan Metzmacher + +Signed-off-by: Günther Deschner +Signed-off-by: Stefan Metzmacher +--- + source3/rpc_server/netlogon/srv_netlog_nt.c | 43 +++++++++++++++++---- + 1 file changed, 35 insertions(+), 8 deletions(-) + +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index 3ffdde34142..d1ce1e94cb5 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -47,6 +47,7 @@ + #include "../lib/tsocket/tsocket.h" + #include "lib/param/param.h" + #include "libsmb/dsgetdcname.h" ++#include "lib/util/util_str_escape.h" + + extern userdom_struct current_user_info; + +@@ -1072,19 +1073,21 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, + NTSTATUS status; + bool schannel_global_required = (lp_server_schannel() == true) ? true:false; + struct loadparm_context *lp_ctx; ++ struct netlogon_creds_CredentialState *creds = NULL; ++ enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; ++ uint16_t opnum = p->opnum; ++ const char *opname = ""; + + if (creds_out != NULL) { + *creds_out = NULL; + } + +- if (schannel_global_required) { +- if (p->auth.auth_type != DCERPC_AUTH_TYPE_SCHANNEL) { +- DBG_ERR("[%s] is not using schannel\n", +- computer_name); +- return NT_STATUS_ACCESS_DENIED; +- } ++ if (opnum < ndr_table_netlogon.num_calls) { ++ opname = ndr_table_netlogon.calls[opnum].name; + } + ++ auth_type = p->auth.auth_type; ++ + lp_ctx = loadparm_init_s3(mem_ctx, loadparm_s3_helpers()); + if (lp_ctx == NULL) { + DEBUG(0, ("loadparm_init_s3 failed\n")); +@@ -1093,9 +1096,33 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, + + status = schannel_check_creds_state(mem_ctx, lp_ctx, + computer_name, received_authenticator, +- return_authenticator, creds_out); ++ return_authenticator, &creds); + talloc_unlink(mem_ctx, lp_ctx); +- return status; ++ ++ if (!NT_STATUS_IS_OK(status)) { ++ ZERO_STRUCTP(return_authenticator); ++ return status; ++ } ++ ++ if (schannel_global_required) { ++ if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { ++ *creds_out = creds; ++ return NT_STATUS_OK; ++ } ++ ++ 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)); ++ TALLOC_FREE(creds); ++ ZERO_STRUCTP(return_authenticator); ++ return NT_STATUS_ACCESS_DENIED; ++ } ++ ++ *creds_out = creds; ++ return NT_STATUS_OK; + } + + +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-15.patch samba-4.11.6+dfsg/debian/patches/zerologon-15.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-15.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-15.patch 2020-09-18 16:32:40.000000000 +0000 @@ -0,0 +1,50 @@ +From 615cc75074b0f51734da261dc9b57ad209780e13 Mon Sep 17 00:00:00 2001 +From: =?utf8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 17 Sep 2020 14:23:16 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: support + "server require schannel:WORKSTATION$ = no" +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +This allows to add expections for individual workstations, when using "server schannel = yes". +"server schannel = auto" is very insecure and will be removed soon. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Pair-Programmed-With: Stefan Metzmacher + +Signed-off-by: Günther Deschner +Signed-off-by: Stefan Metzmacher +--- + source3/rpc_server/netlogon/srv_netlog_nt.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index d1ce1e94cb5..63dd9dc0d5f 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -1072,6 +1072,7 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, + { + NTSTATUS status; + bool schannel_global_required = (lp_server_schannel() == true) ? true:false; ++ bool schannel_required = schannel_global_required; + struct loadparm_context *lp_ctx; + struct netlogon_creds_CredentialState *creds = NULL; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; +@@ -1104,7 +1105,11 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, + return status; + } + +- if (schannel_global_required) { ++ schannel_required = lp_parm_bool(GLOBAL_SECTION_SNUM, ++ "server require schannel", ++ creds->account_name, ++ schannel_global_required); ++ if (schannel_required) { + if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + *creds_out = creds; + return NT_STATUS_OK; +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-16.patch samba-4.11.6+dfsg/debian/patches/zerologon-16.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-16.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-16.patch 2020-09-18 16:32:44.000000000 +0000 @@ -0,0 +1,127 @@ +From 86c54d3a270ab984bfc7c7c0cc334210ed7956ce Mon Sep 17 00:00:00 2001 +From: =?utf8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 17 Sep 2020 14:42:52 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: log + warnings about unsecure configurations +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf8 +Content-Transfer-Encoding: 8bit + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Pair-Programmed-With: Stefan Metzmacher + +Signed-off-by: Günther Deschner +Signed-off-by: Stefan Metzmacher +--- + source3/rpc_server/netlogon/srv_netlog_nt.c | 70 +++++++++++++++++++-- + 1 file changed, 66 insertions(+), 4 deletions(-) + +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index 63dd9dc0d5f..3221ebaa2e2 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -1073,11 +1073,13 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, + NTSTATUS status; + bool schannel_global_required = (lp_server_schannel() == true) ? true:false; + bool schannel_required = schannel_global_required; ++ const char *explicit_opt = NULL; + struct loadparm_context *lp_ctx; + struct netlogon_creds_CredentialState *creds = NULL; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + uint16_t opnum = p->opnum; + const char *opname = ""; ++ static bool warned_global_once = false; + + if (creds_out != NULL) { + *creds_out = NULL; +@@ -1105,10 +1107,20 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, + return status; + } + +- schannel_required = lp_parm_bool(GLOBAL_SECTION_SNUM, +- "server require schannel", +- creds->account_name, +- schannel_global_required); ++ /* ++ * We don't use lp_parm_bool(), as we ++ * need the explicit_opt pointer in order to ++ * adjust the debug messages. ++ */ ++ ++ explicit_opt = lp_parm_const_string(GLOBAL_SECTION_SNUM, ++ "server require schannel", ++ creds->account_name, ++ NULL); ++ if (explicit_opt != NULL) { ++ schannel_required = lp_bool(explicit_opt); ++ } ++ + if (schannel_required) { + if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { + *creds_out = creds; +@@ -1121,11 +1133,61 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, + opname, opnum, + log_escape(mem_ctx, creds->account_name), + log_escape(mem_ctx, 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)); + TALLOC_FREE(creds); + ZERO_STRUCTP(return_authenticator); + 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 " ++ "client_account[%s] client_computer_name[%s]\n", ++ opname, opnum, ++ log_escape(mem_ctx, creds->account_name), ++ log_escape(mem_ctx, 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)); ++ ++ *creds_out = creds; ++ return 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(mem_ctx, creds->account_name), ++ log_escape(mem_ctx, 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)); ++ } 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)); ++ 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)); ++ } ++ + *creds_out = creds; + return NT_STATUS_OK; + } +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-17.patch samba-4.11.6+dfsg/debian/patches/zerologon-17.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-17.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-17.patch 2020-09-18 16:32:48.000000000 +0000 @@ -0,0 +1,101 @@ +From 572a41b24e7cb1b7d52f4021e0fef257cc0563eb Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 17 Sep 2020 17:27:54 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): docs-xml: document 'server require + schannel:COMPUTERACCOUNT' + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Stefan Metzmacher +--- + .../smbdotconf/security/serverschannel.xml | 69 +++++++++++++++---- + 1 file changed, 54 insertions(+), 15 deletions(-) + +diff --git a/docs-xml/smbdotconf/security/serverschannel.xml b/docs-xml/smbdotconf/security/serverschannel.xml +index 489492d79b1..b682d086f76 100644 +--- a/docs-xml/smbdotconf/security/serverschannel.xml ++++ b/docs-xml/smbdotconf/security/serverschannel.xml +@@ -7,26 +7,65 @@ + + + +- This option is deprecated with Samba 4.8 and will be removed in future. +- At the same time the default changed to yes, which will be the +- hardcoded behavior in future. If you have the need for the behavior of "auto" +- to be kept, please file a bug at https://bugzilla.samba.org. ++ 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 controls whether the server offers or even demands the use of the netlogon schannel. +- no does not offer the schannel, auto offers the schannel but does not enforce it, and yes denies access if the client is not able to speak netlogon schannel. +- This is only the case for Windows NT4 before SP4. +- +- ++ Samba will complain in the log files at log level 0, ++ about the security problem if the option is not set to "yes". ++ + +- Please note that with this set to no, you will have to apply the WindowsXP +- WinXP_SignOrSeal.reg registry patch found in the docs/registry subdirectory of the Samba distribution tarball. +- ++ See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497 ++ ++ ++ If you still have legacy domain members use the option. ++ ++ ++ This option yields precedence to the option. ++ + + + yes +-auto ++ ++ ++ ++ ++ ++ If you still have legacy domain members, which required "server schannel = auto" before, ++ it is possible to specify explicit expection per computer account ++ by using 'server require schannel:COMPUTERACCOUNT = no' as option. ++ Note that COMPUTERACCOUNT has to be the sAMAccountName value of ++ the computer account (including the trailing '$' sign). ++ ++ ++ ++ Samba will complain in the log files at log level 0, ++ 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. ++ ++ ++ ++ Samba will warn in the log files at log level 5, ++ if a setting is still needed for the specified computer account. ++ ++ ++ ++ See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497 ++ ++ ++ This option takes precedence to the option. ++ ++ ++ server require schannel:LEGACYCOMPUTER1$ = no ++ server require schannel:NASBOX$ = no ++ server require schannel:LEGACYCOMPUTER2$ = no ++ ++ ++ + +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-18.patch samba-4.11.6+dfsg/debian/patches/zerologon-18.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-18.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-18.patch 2020-09-18 16:32:51.000000000 +0000 @@ -0,0 +1,98 @@ +From 337e4da4daa564f90bfcde1bd8a30cb269fd54a9 Mon Sep 17 00:00:00 2001 +From: Gary Lockyer +Date: Fri, 18 Sep 2020 12:39:54 +1200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s4 torture rpc: Test empty machine + acct pwd + +Ensure that an empty machine account password can't be set by +netr_ServerPasswordSet2 + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Gary Lockyer +--- + source4/torture/rpc/netlogon.c | 64 +++++++++++++++------------------- + 1 file changed, 29 insertions(+), 35 deletions(-) + +diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c +index f966ff6865b..d4bf8ccadbe 100644 +--- a/source4/torture/rpc/netlogon.c ++++ b/source4/torture/rpc/netlogon.c +@@ -725,45 +725,39 @@ static bool test_SetPassword2_with_flags(struct torture_context *tctx, + + cli_credentials_set_password(machine_credentials, password, CRED_SPECIFIED); + +- if (!torture_setting_bool(tctx, "dangerous", false)) { +- torture_comment(tctx, +- "Not testing ability to set password to '', enable dangerous tests to perform this test\n"); ++ /* ++ * As a consequence of CVE-2020-1472(ZeroLogon) ++ * Samba explicitly disallows the setting of an empty machine account ++ * password. ++ * ++ * Note that this may fail against Windows, and leave a machine account ++ * with an empty password. ++ */ ++ password = ""; ++ encode_pw_buffer(password_buf.data, password, STR_UNICODE); ++ if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { ++ netlogon_creds_aes_encrypt(creds, password_buf.data, 516); + } else { +- /* by changing the machine password to "" +- * we check if the server uses password restrictions +- * for ServerPasswordSet2 +- * (win2k3 accepts "") +- */ +- password = ""; +- encode_pw_buffer(password_buf.data, password, STR_UNICODE); +- if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { +- netlogon_creds_aes_encrypt(creds, password_buf.data, 516); +- } else { +- netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); +- } +- memcpy(new_password.data, password_buf.data, 512); +- new_password.length = IVAL(password_buf.data, 512); +- +- torture_comment(tctx, +- "Testing ServerPasswordSet2 on machine account\n"); +- torture_comment(tctx, +- "Changing machine account password to '%s'\n", password); +- +- netlogon_creds_client_authenticator(creds, &credential); +- +- torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerPasswordSet2_r(b, tctx, &r), +- "ServerPasswordSet2 failed"); +- torture_assert_ntstatus_ok(tctx, r.out.result, "ServerPasswordSet2 failed"); ++ netlogon_creds_arcfour_crypt(creds, password_buf.data, 516); ++ } ++ memcpy(new_password.data, password_buf.data, 512); ++ new_password.length = IVAL(password_buf.data, 512); + +- if (!netlogon_creds_client_check(creds, &r.out.return_authenticator->cred)) { +- torture_comment(tctx, "Credential chaining failed\n"); +- } ++ torture_comment(tctx, ++ "Testing ServerPasswordSet2 on machine account\n"); ++ torture_comment(tctx, ++ "Changing machine account password to '%s'\n", password); + +- cli_credentials_set_password(machine_credentials, password, CRED_SPECIFIED); +- } ++ netlogon_creds_client_authenticator(creds, &credential); + +- torture_assert(tctx, test_SetupCredentials(p, tctx, machine_credentials, &creds), +- "ServerPasswordSet failed to actually change the password"); ++ torture_assert_ntstatus_ok( ++ tctx, dcerpc_netr_ServerPasswordSet2_r(b, tctx, &r), ++ "ServerPasswordSet2 failed"); ++ torture_assert_ntstatus_equal( ++ tctx, ++ r.out.result, ++ NT_STATUS_WRONG_PASSWORD, ++ "ServerPasswordSet2 did not return NT_STATUS_WRONG_PASSWORD"); + + /* now try a random password */ + password = generate_random_password(tctx, 8, 255); +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-19.patch samba-4.11.6+dfsg/debian/patches/zerologon-19.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-19.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-19.patch 2020-09-18 16:32:55.000000000 +0000 @@ -0,0 +1,374 @@ +From db344db0efb0eff16211e6bb7dbf02501278c890 Mon Sep 17 00:00:00 2001 +From: Gary Lockyer +Date: Fri, 18 Sep 2020 15:57:34 +1200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s4 torture rpc: repeated bytes in + client challenge + +Ensure that client challenges with the first 5 bytes identical are +rejected. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Gary Lockyer + +[abartlet@samba.org: backported from master as test order was flipped] +--- + source4/torture/rpc/netlogon.c | 335 +++++++++++++++++++++++++++++++++ + 1 file changed, 335 insertions(+) + +diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c +index d4bf8ccadbe..da4d407c627 100644 +--- a/source4/torture/rpc/netlogon.c ++++ b/source4/torture/rpc/netlogon.c +@@ -486,6 +486,325 @@ bool test_SetupCredentialsPipe(const struct dcerpc_pipe *p1, + return true; + } + ++static bool test_ServerReqChallenge( ++ struct torture_context *tctx, ++ struct dcerpc_pipe *p, ++ struct cli_credentials *credentials) ++{ ++ struct netr_ServerReqChallenge r; ++ struct netr_Credential credentials1, credentials2, credentials3; ++ 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 out_negotiate_flags = 0; ++ const struct samr_Password *mach_password = NULL; ++ enum netr_SchannelType sec_chan_type = 0; ++ struct netlogon_creds_CredentialState *creds = NULL; ++ const char *account_name = NULL; ++ ++ machine_name = cli_credentials_get_workstation(credentials); ++ mach_password = cli_credentials_get_nt_hash(credentials, tctx); ++ account_name = cli_credentials_get_username(credentials); ++ sec_chan_type = cli_credentials_get_secure_channel_type(credentials); ++ ++ torture_comment(tctx, "Testing ServerReqChallenge\n"); ++ ++ r.in.server_name = NULL; ++ r.in.computer_name = machine_name; ++ r.in.credentials = &credentials1; ++ r.out.return_credentials = &credentials2; ++ ++ netlogon_creds_random_challenge(&credentials1); ++ ++ torture_assert_ntstatus_ok( ++ tctx, ++ dcerpc_netr_ServerReqChallenge_r(b, tctx, &r), ++ "ServerReqChallenge failed"); ++ torture_assert_ntstatus_ok( ++ tctx, ++ r.out.result, ++ "ServerReqChallenge failed"); ++ a.in.server_name = NULL; ++ a.in.account_name = account_name; ++ a.in.secure_channel_type = sec_chan_type; ++ a.in.computer_name = machine_name; ++ a.in.negotiate_flags = &in_negotiate_flags; ++ a.out.negotiate_flags = &out_negotiate_flags; ++ a.in.credentials = &credentials3; ++ a.out.return_credentials = &credentials3; ++ ++ creds = netlogon_creds_client_init(tctx, a.in.account_name, ++ a.in.computer_name, ++ a.in.secure_channel_type, ++ &credentials1, &credentials2, ++ mach_password, &credentials3, ++ in_negotiate_flags); ++ ++ torture_assert(tctx, creds != NULL, "memory allocation"); ++ ++ torture_comment(tctx, "Testing ServerAuthenticate2\n"); ++ ++ torture_assert_ntstatus_ok( ++ tctx, ++ dcerpc_netr_ServerAuthenticate2_r(b, tctx, &a), ++ "ServerAuthenticate2 failed"); ++ torture_assert_ntstatus_equal( ++ tctx, ++ a.out.result, ++ NT_STATUS_OK, ++ "ServerAuthenticate2 unexpected"); ++ ++ return true; ++} ++ ++static bool test_ServerReqChallenge_zero_challenge( ++ struct torture_context *tctx, ++ struct dcerpc_pipe *p, ++ struct cli_credentials *credentials) ++{ ++ struct netr_ServerReqChallenge r; ++ struct netr_Credential credentials1, credentials2, credentials3; ++ 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 out_negotiate_flags = 0; ++ const struct samr_Password *mach_password = NULL; ++ enum netr_SchannelType sec_chan_type = 0; ++ struct netlogon_creds_CredentialState *creds = NULL; ++ const char *account_name = NULL; ++ ++ machine_name = cli_credentials_get_workstation(credentials); ++ mach_password = cli_credentials_get_nt_hash(credentials, tctx); ++ account_name = cli_credentials_get_username(credentials); ++ sec_chan_type = cli_credentials_get_secure_channel_type(credentials); ++ ++ torture_comment(tctx, "Testing ServerReqChallenge\n"); ++ ++ r.in.server_name = NULL; ++ r.in.computer_name = machine_name; ++ r.in.credentials = &credentials1; ++ r.out.return_credentials = &credentials2; ++ ++ /* ++ * Set the client challenge to zero, this should fail ++ * CVE-2020-1472(ZeroLogon) ++ * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 ++ */ ++ ZERO_STRUCT(credentials1); ++ ++ torture_assert_ntstatus_ok( ++ tctx, ++ dcerpc_netr_ServerReqChallenge_r(b, tctx, &r), ++ "ServerReqChallenge failed"); ++ torture_assert_ntstatus_ok( ++ tctx, ++ r.out.result, ++ "ServerReqChallenge failed"); ++ a.in.server_name = NULL; ++ a.in.account_name = account_name; ++ a.in.secure_channel_type = sec_chan_type; ++ a.in.computer_name = machine_name; ++ a.in.negotiate_flags = &in_negotiate_flags; ++ a.out.negotiate_flags = &out_negotiate_flags; ++ a.in.credentials = &credentials3; ++ a.out.return_credentials = &credentials3; ++ ++ creds = netlogon_creds_client_init(tctx, a.in.account_name, ++ a.in.computer_name, ++ a.in.secure_channel_type, ++ &credentials1, &credentials2, ++ mach_password, &credentials3, ++ in_negotiate_flags); ++ ++ torture_assert(tctx, creds != NULL, "memory allocation"); ++ ++ torture_comment(tctx, "Testing ServerAuthenticate2\n"); ++ ++ torture_assert_ntstatus_ok( ++ tctx, ++ dcerpc_netr_ServerAuthenticate2_r(b, tctx, &a), ++ "ServerAuthenticate2 failed"); ++ torture_assert_ntstatus_equal( ++ tctx, ++ a.out.result, ++ NT_STATUS_ACCESS_DENIED, ++ "ServerAuthenticate2 unexpected"); ++ ++ return true; ++} ++ ++static bool test_ServerReqChallenge_5_repeats( ++ struct torture_context *tctx, ++ struct dcerpc_pipe *p, ++ struct cli_credentials *credentials) ++{ ++ struct netr_ServerReqChallenge r; ++ struct netr_Credential credentials1, credentials2, credentials3; ++ 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 out_negotiate_flags = 0; ++ const struct samr_Password *mach_password = NULL; ++ enum netr_SchannelType sec_chan_type = 0; ++ struct netlogon_creds_CredentialState *creds = NULL; ++ const char *account_name = NULL; ++ ++ machine_name = cli_credentials_get_workstation(credentials); ++ mach_password = cli_credentials_get_nt_hash(credentials, tctx); ++ account_name = cli_credentials_get_username(credentials); ++ sec_chan_type = cli_credentials_get_secure_channel_type(credentials); ++ ++ torture_comment(tctx, "Testing ServerReqChallenge\n"); ++ ++ r.in.server_name = NULL; ++ r.in.computer_name = machine_name; ++ r.in.credentials = &credentials1; ++ r.out.return_credentials = &credentials2; ++ ++ /* ++ * Set the first 5 bytes of the client challenge to the same value, ++ * this should fail CVE-2020-1472(ZeroLogon) ++ * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 ++ */ ++ credentials1.data[0] = 'A'; ++ credentials1.data[1] = 'A'; ++ credentials1.data[2] = 'A'; ++ credentials1.data[3] = 'A'; ++ credentials1.data[4] = 'A'; ++ credentials1.data[5] = 'B'; ++ credentials1.data[6] = 'C'; ++ credentials1.data[7] = 'D'; ++ ++ torture_assert_ntstatus_ok( ++ tctx, ++ dcerpc_netr_ServerReqChallenge_r(b, tctx, &r), ++ "ServerReqChallenge failed"); ++ torture_assert_ntstatus_ok( ++ tctx, ++ r.out.result, ++ "ServerReqChallenge failed"); ++ a.in.server_name = NULL; ++ a.in.account_name = account_name; ++ a.in.secure_channel_type = sec_chan_type; ++ a.in.computer_name = machine_name; ++ a.in.negotiate_flags = &in_negotiate_flags; ++ a.out.negotiate_flags = &out_negotiate_flags; ++ a.in.credentials = &credentials3; ++ a.out.return_credentials = &credentials3; ++ ++ creds = netlogon_creds_client_init(tctx, a.in.account_name, ++ a.in.computer_name, ++ a.in.secure_channel_type, ++ &credentials1, &credentials2, ++ mach_password, &credentials3, ++ in_negotiate_flags); ++ ++ torture_assert(tctx, creds != NULL, "memory allocation"); ++ ++ torture_comment(tctx, "Testing ServerAuthenticate2\n"); ++ ++ torture_assert_ntstatus_ok( ++ tctx, ++ dcerpc_netr_ServerAuthenticate2_r(b, tctx, &a), ++ "ServerAuthenticate2 failed"); ++ torture_assert_ntstatus_equal( ++ tctx, ++ a.out.result, ++ NT_STATUS_ACCESS_DENIED, ++ "ServerAuthenticate2 unexpected"); ++ ++ return true; ++} ++ ++static bool test_ServerReqChallenge_4_repeats( ++ struct torture_context *tctx, ++ struct dcerpc_pipe *p, ++ struct cli_credentials *credentials) ++{ ++ struct netr_ServerReqChallenge r; ++ struct netr_Credential credentials1, credentials2, credentials3; ++ 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 out_negotiate_flags = 0; ++ const struct samr_Password *mach_password = NULL; ++ enum netr_SchannelType sec_chan_type = 0; ++ struct netlogon_creds_CredentialState *creds = NULL; ++ const char *account_name = NULL; ++ ++ machine_name = cli_credentials_get_workstation(credentials); ++ mach_password = cli_credentials_get_nt_hash(credentials, tctx); ++ account_name = cli_credentials_get_username(credentials); ++ sec_chan_type = cli_credentials_get_secure_channel_type(credentials); ++ ++ torture_comment(tctx, "Testing ServerReqChallenge\n"); ++ ++ r.in.server_name = NULL; ++ r.in.computer_name = machine_name; ++ r.in.credentials = &credentials1; ++ r.out.return_credentials = &credentials2; ++ ++ /* ++ * Set the first 4 bytes of the client challenge to the same ++ * value, this should pass as 5 bytes identical are needed to ++ * fail for CVE-2020-1472(ZeroLogon) ++ * ++ * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 ++ */ ++ credentials1.data[0] = 'A'; ++ credentials1.data[1] = 'A'; ++ credentials1.data[2] = 'A'; ++ credentials1.data[3] = 'A'; ++ credentials1.data[4] = 'B'; ++ credentials1.data[5] = 'C'; ++ credentials1.data[6] = 'D'; ++ credentials1.data[7] = 'E'; ++ ++ torture_assert_ntstatus_ok( ++ tctx, ++ dcerpc_netr_ServerReqChallenge_r(b, tctx, &r), ++ "ServerReqChallenge failed"); ++ torture_assert_ntstatus_ok( ++ tctx, ++ r.out.result, ++ "ServerReqChallenge failed"); ++ a.in.server_name = NULL; ++ a.in.account_name = account_name; ++ a.in.secure_channel_type = sec_chan_type; ++ a.in.computer_name = machine_name; ++ a.in.negotiate_flags = &in_negotiate_flags; ++ a.out.negotiate_flags = &out_negotiate_flags; ++ a.in.credentials = &credentials3; ++ a.out.return_credentials = &credentials3; ++ ++ creds = netlogon_creds_client_init(tctx, a.in.account_name, ++ a.in.computer_name, ++ a.in.secure_channel_type, ++ &credentials1, &credentials2, ++ mach_password, &credentials3, ++ in_negotiate_flags); ++ ++ torture_assert(tctx, creds != NULL, "memory allocation"); ++ ++ torture_comment(tctx, "Testing ServerAuthenticate2\n"); ++ ++ torture_assert_ntstatus_ok( ++ tctx, ++ dcerpc_netr_ServerAuthenticate2_r(b, tctx, &a), ++ "ServerAuthenticate2 failed"); ++ torture_assert_ntstatus_equal( ++ tctx, ++ a.out.result, ++ NT_STATUS_OK, ++ "ServerAuthenticate2 unexpected"); ++ ++ return true; ++} ++ + /* + try a change password for our machine account + */ +@@ -4954,6 +5273,22 @@ struct torture_suite *torture_rpc_netlogon(TALLOC_CTX *mem_ctx) + torture_rpc_tcase_add_test(tcase, "lsa_over_netlogon", test_lsa_over_netlogon); + torture_rpc_tcase_add_test_creds(tcase, "SetupCredentialsDowngrade", test_SetupCredentialsDowngrade); + ++ torture_rpc_tcase_add_test_creds( ++ tcase, ++ "ServerReqChallenge", ++ test_ServerReqChallenge); ++ torture_rpc_tcase_add_test_creds( ++ tcase, ++ "ServerReqChallenge_zero_challenge", ++ test_ServerReqChallenge_zero_challenge); ++ torture_rpc_tcase_add_test_creds( ++ tcase, ++ "ServerReqChallenge_5_repeats", ++ test_ServerReqChallenge_5_repeats); ++ torture_rpc_tcase_add_test_creds( ++ tcase, ++ "ServerReqChallenge_4_repeats", ++ test_ServerReqChallenge_4_repeats); + return suite; + } + +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-1.patch samba-4.11.6+dfsg/debian/patches/zerologon-1.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-1.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-1.patch 2020-09-18 16:31:52.000000000 +0000 @@ -0,0 +1,60 @@ +From 6941fa1ff8336af0f77728aaf8162b59aa704988 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:04:57 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): libcli/auth: add + netlogon_creds_random_challenge() + +It's good to have just a single isolated function that will generate +random challenges, in future we can add some logic in order to +avoid weak values, which are likely to be rejected by a server. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Stefan Metzmacher +--- + libcli/auth/credentials.c | 7 +++++++ + libcli/auth/proto.h | 3 +++ + 2 files changed, 10 insertions(+) + +diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c +index 319dacdac0b..c79f5e2ce24 100644 +--- a/libcli/auth/credentials.c ++++ b/libcli/auth/credentials.c +@@ -30,9 +30,16 @@ + #include + #include + ++void netlogon_creds_random_challenge(struct netr_Credential *challenge) ++{ ++ ZERO_STRUCTP(challenge); ++ generate_random_buffer(challenge->data, sizeof(challenge->data)); ++} ++ + static void netlogon_creds_step_crypt(struct netlogon_creds_CredentialState *creds, + const struct netr_Credential *in, + struct netr_Credential *out) ++ + { + if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { + AES_KEY key; +diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h +index afd7f0d148d..19a0e846357 100644 +--- a/libcli/auth/proto.h ++++ b/libcli/auth/proto.h +@@ -11,10 +11,13 @@ + + /* The following definitions come from /home/jeremy/src/samba/git/master/source3/../source4/../libcli/auth/credentials.c */ + ++void netlogon_creds_random_challenge(struct netr_Credential *challenge); ++ + void netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key); + void netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key); + void netlogon_creds_des_encrypt(struct netlogon_creds_CredentialState *creds, struct samr_Password *pass); + void netlogon_creds_des_decrypt(struct netlogon_creds_CredentialState *creds, struct samr_Password *pass); ++ + NTSTATUS netlogon_creds_arcfour_crypt(struct netlogon_creds_CredentialState *creds, + uint8_t *data, + size_t len); +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-2.patch samba-4.11.6+dfsg/debian/patches/zerologon-2.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-2.patch 2020-09-18 16:31:55.000000000 +0000 @@ -0,0 +1,155 @@ +From 691d854c141cfe177f4c18ed045e38725504aaf3 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:07:30 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s4:torture/rpc: make use of + netlogon_creds_random_challenge() + +This will avoid getting flakey tests once our server starts to +reject weak challenges. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Stefan Metzmacher +--- + source4/torture/rpc/lsa.c | 2 +- + source4/torture/rpc/netlogon.c | 34 ++++++++++++---------------------- + 2 files changed, 13 insertions(+), 23 deletions(-) + +diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c +index 0ce113feb5d..52370f4fe8e 100644 +--- a/source4/torture/rpc/lsa.c ++++ b/source4/torture/rpc/lsa.c +@@ -2872,7 +2872,7 @@ static bool check_pw_with_ServerAuthenticate3(struct dcerpc_pipe *p, + r.in.credentials = &credentials1; + r.out.return_credentials = &credentials2; + +- generate_random_buffer(credentials1.data, sizeof(credentials1.data)); ++ netlogon_creds_random_challenge(&credentials1); + + torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r), + "ServerReqChallenge failed"); +diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c +index 94fe4020fa9..f966ff6865b 100644 +--- a/source4/torture/rpc/netlogon.c ++++ b/source4/torture/rpc/netlogon.c +@@ -160,7 +160,7 @@ bool test_SetupCredentials(struct dcerpc_pipe *p, struct torture_context *tctx, + r.in.credentials = &credentials1; + r.out.return_credentials = &credentials2; + +- generate_random_buffer(credentials1.data, sizeof(credentials1.data)); ++ netlogon_creds_random_challenge(&credentials1); + + torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r), + "ServerReqChallenge failed"); +@@ -229,7 +229,7 @@ bool test_SetupCredentials2ex(struct dcerpc_pipe *p, struct torture_context *tct + r.in.credentials = &credentials1; + r.out.return_credentials = &credentials2; + +- generate_random_buffer(credentials1.data, sizeof(credentials1.data)); ++ netlogon_creds_random_challenge(&credentials1); + + torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r), + "ServerReqChallenge failed"); +@@ -324,7 +324,7 @@ bool test_SetupCredentials3(struct dcerpc_pipe *p, struct torture_context *tctx, + r.in.credentials = &credentials1; + r.out.return_credentials = &credentials2; + +- generate_random_buffer(credentials1.data, sizeof(credentials1.data)); ++ netlogon_creds_random_challenge(&credentials1); + + torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r), + "ServerReqChallenge failed"); +@@ -396,7 +396,7 @@ bool test_SetupCredentialsDowngrade(struct torture_context *tctx, + r.in.credentials = &credentials1; + r.out.return_credentials = &credentials2; + +- generate_random_buffer(credentials1.data, sizeof(credentials1.data)); ++ netlogon_creds_random_challenge(&credentials1); + + torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r), + "ServerReqChallenge failed"); +@@ -1283,7 +1283,7 @@ static bool test_ServerReqChallengeGlobal(struct torture_context *tctx, + r.in.credentials = &credentials1; + r.out.return_credentials = &credentials2; + +- generate_random_buffer(credentials1.data, sizeof(credentials1.data)); ++ netlogon_creds_random_challenge(&credentials1); + + torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r), + "ServerReqChallenge failed on b1"); +@@ -1372,7 +1372,7 @@ static bool test_ServerReqChallengeReuseGlobal(struct torture_context *tctx, + r.in.credentials = &credentials1; + r.out.return_credentials = &credentials2; + +- generate_random_buffer(credentials1.data, sizeof(credentials1.data)); ++ netlogon_creds_random_challenge(&credentials1); + + torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r), + "ServerReqChallenge failed on b1"); +@@ -1461,7 +1461,7 @@ static bool test_ServerReqChallengeReuseGlobal2(struct torture_context *tctx, + r.in.credentials = &credentials1; + r.out.return_credentials = &credentials2; + +- generate_random_buffer(credentials1.data, sizeof(credentials1.data)); ++ netlogon_creds_random_challenge(&credentials1); + + torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r), + "ServerReqChallenge failed on b1"); +@@ -1551,7 +1551,7 @@ static bool test_ServerReqChallengeReuseGlobal3(struct torture_context *tctx, + r.in.credentials = &credentials1; + r.out.return_credentials = &credentials2; + +- generate_random_buffer(credentials1.data, sizeof(credentials1.data)); ++ netlogon_creds_random_challenge(&credentials1); + + torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r), + "ServerReqChallenge failed on b1"); +@@ -1643,8 +1643,7 @@ static bool test_ServerReqChallengeReuseGlobal4(struct torture_context *tctx, + r.in.credentials = &credentials1_random; + r.out.return_credentials = &credentials_discard; + +- generate_random_buffer(credentials1_random.data, +- sizeof(credentials1_random.data)); ++ netlogon_creds_random_challenge(&credentials1_random); + + torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r), + "ServerReqChallenge failed on b1"); +@@ -1656,7 +1655,7 @@ static bool test_ServerReqChallengeReuseGlobal4(struct torture_context *tctx, + r.in.credentials = &credentials1; + r.out.return_credentials = &credentials2; + +- generate_random_buffer(credentials1.data, sizeof(credentials1.data)); ++ netlogon_creds_random_challenge(&credentials1); + + torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r), + "ServerReqChallenge failed on b1"); +@@ -1667,16 +1666,7 @@ static bool test_ServerReqChallengeReuseGlobal4(struct torture_context *tctx, + r.in.credentials = &credentials1_random; + r.out.return_credentials = &credentials_discard; + +- generate_random_buffer(credentials1_random.data, +- sizeof(credentials1_random.data)); +- +- r.in.server_name = NULL; +- r.in.computer_name = "CHALTEST3"; +- r.in.credentials = &credentials1_random; +- r.out.return_credentials = &credentials_discard; +- +- generate_random_buffer(credentials1_random.data, +- sizeof(credentials1_random.data)); ++ netlogon_creds_random_challenge(&credentials1_random); + + torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b1, tctx, &r), + "ServerReqChallenge failed on b1"); +@@ -1752,7 +1742,7 @@ static bool test_ServerReqChallengeReuse(struct torture_context *tctx, + r.in.credentials = &credentials1; + r.out.return_credentials = &credentials2; + +- generate_random_buffer(credentials1.data, sizeof(credentials1.data)); ++ netlogon_creds_random_challenge(&credentials1); + + torture_assert_ntstatus_ok(tctx, dcerpc_netr_ServerReqChallenge_r(b, tctx, &r), + "ServerReqChallenge"); +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-3.patch samba-4.11.6+dfsg/debian/patches/zerologon-3.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-3.patch 2020-09-18 16:31:59.000000000 +0000 @@ -0,0 +1,33 @@ +From f7b0e7a6dde36bd6721c7f8d926dfdd0d70ba68e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:08:38 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): libcli/auth: make use of + netlogon_creds_random_challenge() in netlogon_creds_cli.c + +This will avoid getting rejected by the server if we generate +a weak challenge. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Stefan Metzmacher +--- + libcli/auth/netlogon_creds_cli.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c +index 50a5f50a57d..0b31dc91b4b 100644 +--- a/libcli/auth/netlogon_creds_cli.c ++++ b/libcli/auth/netlogon_creds_cli.c +@@ -1177,8 +1177,7 @@ static void netlogon_creds_cli_auth_challenge_start(struct tevent_req *req) + + TALLOC_FREE(state->creds); + +- generate_random_buffer(state->client_challenge.data, +- sizeof(state->client_challenge.data)); ++ netlogon_creds_random_challenge(&state->client_challenge); + + subreq = dcerpc_netr_ServerReqChallenge_send(state, state->ev, + state->binding_handle, +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-4.patch samba-4.11.6+dfsg/debian/patches/zerologon-4.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-4.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-4.patch 2020-09-18 16:32:02.000000000 +0000 @@ -0,0 +1,32 @@ +From a71bc6c974db72fd3ef0a234fb9a0ef4fdc4d963 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:10:53 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s3:rpc_server:netlogon: make use of + netlogon_creds_random_challenge() + +This is not strictly needed, but makes things more clear. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Stefan Metzmacher +--- + source3/rpc_server/netlogon/srv_netlog_nt.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index c9aaa90cbb9..3894eecd7ae 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -839,8 +839,7 @@ NTSTATUS _netr_ServerReqChallenge(struct pipes_struct *p, + + pipe_state->client_challenge = *r->in.credentials; + +- generate_random_buffer(pipe_state->server_challenge.data, +- sizeof(pipe_state->server_challenge.data)); ++ netlogon_creds_random_challenge(&pipe_state->server_challenge); + + *r->out.return_credentials = pipe_state->server_challenge; + +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-5.patch samba-4.11.6+dfsg/debian/patches/zerologon-5.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-5.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-5.patch 2020-09-18 16:32:06.000000000 +0000 @@ -0,0 +1,32 @@ +From 35277995d3977c37509ef072e6b5cc785ceb7ee2 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:10:53 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s4:rpc_server:netlogon: make use of + netlogon_creds_random_challenge() + +This is not strictly needed, but makes things more clear. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Stefan Metzmacher +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index ac745e32b02..bb97e86055a 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -90,8 +90,7 @@ static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_cal + + pipe_state->client_challenge = *r->in.credentials; + +- generate_random_buffer(pipe_state->server_challenge.data, +- sizeof(pipe_state->server_challenge.data)); ++ netlogon_creds_random_challenge(&pipe_state->server_challenge); + + *r->out.return_credentials = pipe_state->server_challenge; + +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-6.patch samba-4.11.6+dfsg/debian/patches/zerologon-6.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-6.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-6.patch 2020-09-18 16:32:09.000000000 +0000 @@ -0,0 +1,69 @@ +From 13185dd83563cc7927a511f5d2a4a56cc2186743 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:15:26 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): libcli/auth: add + netlogon_creds_is_random_challenge() to avoid weak values + +This is the check Windows is using, so we won't generate challenges, +which are rejected by Windows DCs (and future Samba DCs). + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Stefan Metzmacher +--- + libcli/auth/credentials.c | 23 ++++++++++++++++++++++- + libcli/auth/proto.h | 1 + + 2 files changed, 23 insertions(+), 1 deletion(-) + +diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c +index c79f5e2ce24..dce0a9151e9 100644 +--- a/libcli/auth/credentials.c ++++ b/libcli/auth/credentials.c +@@ -30,10 +30,31 @@ + #include + #include + ++bool netlogon_creds_is_random_challenge(const struct netr_Credential *challenge) ++{ ++ /* ++ * If none of the first 5 bytes of the client challenge is unique, the ++ * server MUST fail session-key negotiation without further processing ++ * of the following steps. ++ */ ++ ++ if (challenge->data[1] == challenge->data[0] && ++ challenge->data[2] == challenge->data[0] && ++ challenge->data[3] == challenge->data[0] && ++ challenge->data[4] == challenge->data[0]) ++ { ++ return false; ++ } ++ ++ return true; ++} ++ + void netlogon_creds_random_challenge(struct netr_Credential *challenge) + { + ZERO_STRUCTP(challenge); +- generate_random_buffer(challenge->data, sizeof(challenge->data)); ++ while (!netlogon_creds_is_random_challenge(challenge)) { ++ generate_random_buffer(challenge->data, sizeof(challenge->data)); ++ } + } + + static void netlogon_creds_step_crypt(struct netlogon_creds_CredentialState *creds, +diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h +index 19a0e846357..51d5deaab2d 100644 +--- a/libcli/auth/proto.h ++++ b/libcli/auth/proto.h +@@ -11,6 +11,7 @@ + + /* The following definitions come from /home/jeremy/src/samba/git/master/source3/../source4/../libcli/auth/credentials.c */ + ++bool netlogon_creds_is_random_challenge(const struct netr_Credential *challenge); + void netlogon_creds_random_challenge(struct netr_Credential *challenge); + + void netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds, struct netr_LMSessionKey *key); +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-7.patch samba-4.11.6+dfsg/debian/patches/zerologon-7.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-7.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-7.patch 2020-09-18 16:32:13.000000000 +0000 @@ -0,0 +1,81 @@ +From fd05519caa2e738da317432371f42e4967514773 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:17:29 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): libcli/auth: reject weak client + challenges in netlogon_creds_server_init() + +This implements the note from MS-NRPC 3.1.4.1 Session-Key Negotiation: + + 7. If none of the first 5 bytes of the client challenge is unique, the + server MUST fail session-key negotiation without further processing of + the following steps. + +It lets ./zerologon_tester.py from +https://github.com/SecuraBV/CVE-2020-1472.git +report: "Attack failed. Target is probably patched." + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Stefan Metzmacher +--- + libcli/auth/credentials.c | 16 ++++++++++++++++ + libcli/auth/wscript_build | 2 +- + 2 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c +index dce0a9151e9..0ba1d95afd3 100644 +--- a/libcli/auth/credentials.c ++++ b/libcli/auth/credentials.c +@@ -25,6 +25,7 @@ + #include "../lib/crypto/crypto.h" + #include "libcli/auth/libcli_auth.h" + #include "../libcli/security/dom_sid.h" ++#include "lib/util/util_str_escape.h" + + #include "lib/crypto/gnutls_helpers.h" + #include +@@ -534,6 +535,7 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me + { + + struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState); ++ bool ok; + + if (!creds) { + return NULL; +@@ -546,6 +548,20 @@ struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *me + dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data)); + dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash)); + ++ ok = netlogon_creds_is_random_challenge(client_challenge); ++ if (!ok) { ++ DBG_WARNING("CVE-2020-1472(ZeroLogon): " ++ "non-random client challenge rejected for " ++ "client_account[%s] client_computer_name[%s]\n", ++ log_escape(mem_ctx, client_account), ++ log_escape(mem_ctx, client_computer_name)); ++ dump_data(DBGLVL_WARNING, ++ client_challenge->data, ++ sizeof(client_challenge->data)); ++ talloc_free(creds); ++ return NULL; ++ } ++ + creds->computer_name = talloc_strdup(creds, client_computer_name); + if (!creds->computer_name) { + talloc_free(creds); +diff --git a/libcli/auth/wscript_build b/libcli/auth/wscript_build +index 04e2b09eadf..6f7d9a76404 100644 +--- a/libcli/auth/wscript_build ++++ b/libcli/auth/wscript_build +@@ -18,7 +18,7 @@ bld.SAMBA_SUBSYSTEM('NTLM_CHECK', + + bld.SAMBA_SUBSYSTEM('LIBCLI_AUTH', + source='credentials.c session.c smbencrypt.c smbdes.c', +- public_deps='MSRPC_PARSE gnutls GNUTLS_HELPERS', ++ public_deps='MSRPC_PARSE gnutls GNUTLS_HELPERS util_str_escape', + public_headers='credentials.h:domain_credentials.h' + ) + +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-8.patch samba-4.11.6+dfsg/debian/patches/zerologon-8.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-8.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-8.patch 2020-09-18 16:32:16.000000000 +0000 @@ -0,0 +1,94 @@ +From 9b174d71541ec60157c17938551d8c9b429e578f Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 19:20:25 +0200 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon: protect + netr_ServerPasswordSet2 against unencrypted passwords + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Stefan Metzmacher +--- + source4/rpc_server/netlogon/dcerpc_netlogon.c | 60 ++++++++++++++++++- + 1 file changed, 59 insertions(+), 1 deletion(-) + +diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c +index bb97e86055a..a8d8d95130f 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -721,7 +721,10 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal + struct NL_PASSWORD_VERSION version = {}; + const uint32_t *new_version = NULL; + NTSTATUS nt_status; +- DATA_BLOB new_password; ++ DATA_BLOB new_password = data_blob_null; ++ size_t confounder_len; ++ DATA_BLOB dec_blob = data_blob_null; ++ DATA_BLOB enc_blob = data_blob_null; + int ret; + struct samr_CryptPassword password_buf; + +@@ -784,6 +787,61 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal + return NT_STATUS_WRONG_PASSWORD; + } + ++ /* ++ * Make sure the length field was encrypted, ++ * otherwise we are under attack. ++ */ ++ if (new_password.length == r->in.new_password->length) { ++ DBG_WARNING("Length[%zu] field not encrypted\n", ++ new_password.length); ++ return NT_STATUS_WRONG_PASSWORD; ++ } ++ ++ /* ++ * We don't allow empty passwords for machine accounts. ++ */ ++ if (new_password.length < 2) { ++ DBG_WARNING("Empty password Length[%zu]\n", ++ new_password.length); ++ return NT_STATUS_WRONG_PASSWORD; ++ } ++ ++ /* ++ * Make sure the confounder part of CryptPassword ++ * buffer was encrypted, otherwise we are under attack. ++ */ ++ confounder_len = 512 - new_password.length; ++ enc_blob = data_blob_const(r->in.new_password->data, confounder_len); ++ dec_blob = data_blob_const(password_buf.data, confounder_len); ++ if (data_blob_cmp(&dec_blob, &enc_blob) == 0) { ++ DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n", ++ confounder_len); ++ return NT_STATUS_WRONG_PASSWORD; ++ } ++ ++ /* ++ * Check that the password part was actually encrypted, ++ * otherwise we are under attack. ++ */ ++ enc_blob = data_blob_const(r->in.new_password->data + confounder_len, ++ new_password.length); ++ dec_blob = data_blob_const(password_buf.data + confounder_len, ++ new_password.length); ++ if (data_blob_cmp(&dec_blob, &enc_blob) == 0) { ++ DBG_WARNING("Password buffer not encrypted Length[%zu]\n", ++ new_password.length); ++ return NT_STATUS_WRONG_PASSWORD; ++ } ++ ++ /* ++ * don't allow zero buffers ++ */ ++ if (all_zero(new_password.data, new_password.length)) { ++ DBG_WARNING("Password zero buffer Length[%zu]\n", ++ new_password.length); ++ return NT_STATUS_WRONG_PASSWORD; ++ } ++ + /* fetch the old password hashes (at least one of both has to exist) */ + + ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs, +-- +2.28.0 + diff -Nru samba-4.11.6+dfsg/debian/patches/zerologon-9.patch samba-4.11.6+dfsg/debian/patches/zerologon-9.patch --- samba-4.11.6+dfsg/debian/patches/zerologon-9.patch 1970-01-01 00:00:00.000000000 +0000 +++ samba-4.11.6+dfsg/debian/patches/zerologon-9.patch 2020-09-18 16:32:20.000000000 +0000 @@ -0,0 +1,31 @@ +From d5926ad40ffc31a9b0f6e2cb66d47aa58e1e5e4e Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Wed, 16 Sep 2020 12:48:21 -0700 +Subject: [PATCH] CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: Fix mem + leak onto p->mem_ctx in error path of _netr_ServerPasswordSet2(). + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 + +Signed-off-by: Jeremy Allison + +[dbagnall@samba.org, abartlet@samba.org: adapt for indentation +changes] +--- + source3/rpc_server/netlogon/srv_netlog_nt.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c +index 3894eecd7ae..bc5ec654a95 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -1364,6 +1364,7 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, + password_buf.data, + 516); + if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(creds); + return status; + } + } +-- +2.28.0 +