diff --git a/CVE-2020-1472.patch b/CVE-2020-1472.patch new file mode 100644 index 0000000000000000000000000000000000000000..e61592194a87f5f7e904ccef1dec572832943ba5 --- /dev/null +++ b/CVE-2020-1472.patch @@ -0,0 +1,1842 @@ +From 84b8910da08dfa26440405f5e3916f222801859e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:04:57 +0200 +Subject: [PATCH 01/19] 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 | 6 ++++++ + libcli/auth/proto.h | 2 ++ + 2 files changed, 8 insertions(+) + +diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c +index c541eeff470..46259f39306 100644 +--- a/libcli/auth/credentials.c ++++ b/libcli/auth/credentials.c +@@ -33,6 +33,12 @@ + #include + #include + ++void netlogon_creds_random_challenge(struct netr_Credential *challenge) ++{ ++ ZERO_STRUCTP(challenge); ++ generate_random_buffer(challenge->data, sizeof(challenge->data)); ++} ++ + static NTSTATUS netlogon_creds_step_crypt(struct netlogon_creds_CredentialState *creds, + const struct netr_Credential *in, + struct netr_Credential *out) +diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h +index 88f4a7c6c50..396484a5437 100644 +--- a/libcli/auth/proto.h ++++ b/libcli/auth/proto.h +@@ -13,6 +13,8 @@ + + /* 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); ++ + NTSTATUS netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds, + struct netr_LMSessionKey *key); + NTSTATUS netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState *creds, +-- +2.20.1 + + +From 3d9e8bd6735272b528fc10c7d8289044870229d5 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:07:30 +0200 +Subject: [PATCH 02/19] 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 548ebf8a090..0b1346e055a 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 65188d2dc85..826793717e7 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.20.1 + + +From 8cf3efad0e15c3b001cc23d1e1280a91878f778d Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:08:38 +0200 +Subject: [PATCH 03/19] 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 407cb471cbc..12cb3149ff6 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.20.1 + + +From 2f21d4bd6c68016b1e9c737dc6614131afa2181d Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:10:53 +0200 +Subject: [PATCH 04/19] 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 52b17c10e61..516bbd7f6a8 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -840,8 +840,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.20.1 + + +From b4df5225f750e686f742466e28f13c55a261674f Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:10:53 +0200 +Subject: [PATCH 05/19] 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 0ab55afeab0..7d1b9db0b86 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.20.1 + + +From 18639a64e81866767eaf3e4ea118d932e1cf0d0c Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:15:26 +0200 +Subject: [PATCH 06/19] 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 46259f39306..54a20100b51 100644 +--- a/libcli/auth/credentials.c ++++ b/libcli/auth/credentials.c +@@ -33,10 +33,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 NTSTATUS netlogon_creds_step_crypt(struct netlogon_creds_CredentialState *creds, +diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h +index 396484a5437..a62668f088f 100644 +--- a/libcli/auth/proto.h ++++ b/libcli/auth/proto.h +@@ -13,6 +13,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); + + NTSTATUS netlogon_creds_des_encrypt_LMKey(struct netlogon_creds_CredentialState *creds, +-- +2.20.1 + + +From 2eb0f87de8c9d86fad4ca1bd74f05d15af98f56e Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 16:17:29 +0200 +Subject: [PATCH 07/19] 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 | 17 ++++++++++++++++- + libcli/auth/wscript_build | 2 +- + 2 files changed, 17 insertions(+), 2 deletions(-) + +diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c +index 54a20100b51..23339d98bfa 100644 +--- a/libcli/auth/credentials.c ++++ b/libcli/auth/credentials.c +@@ -24,6 +24,7 @@ + #include "system/time.h" + #include "libcli/auth/libcli_auth.h" + #include "../libcli/security/dom_sid.h" ++#include "lib/util/util_str_escape.h" + + #ifndef HAVE_GNUTLS_AES_CFB8 + #include "lib/crypto/aes.h" +@@ -704,7 +705,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); + NTSTATUS status; +- ++ bool ok; + + if (!creds) { + return NULL; +@@ -717,6 +718,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 41937623630..2a6a7468e45 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.20.1 + + +From 592e8e9acdca472115fdf69a3d0904f1740f4fb0 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 19:20:25 +0200 +Subject: [PATCH 08/19] 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 7d1b9db0b86..4aa6f256a07 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -724,7 +724,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; + +@@ -790,6 +793,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.20.1 + + +From ff66560357d3eb23ce71f6667443e47a0c491833 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Wed, 16 Sep 2020 12:48:21 -0700 +Subject: [PATCH 09/19] 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 +--- + 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 516bbd7f6a8..b26efb78bab 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -1385,6 +1385,7 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, + 516); + } + if (!NT_STATUS_IS_OK(status)) { ++ TALLOC_FREE(creds); + return status; + } + +-- +2.20.1 + + +From aa57f084ca2cf16e323d172634eacf34db3ff0d7 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Wed, 16 Sep 2020 12:53:50 -0700 +Subject: [PATCH 10/19] 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 b26efb78bab..693e254b051 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -1343,9 +1343,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, +@@ -1389,18 +1394,99 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, + return status; + } + +- 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.20.1 + + +From 1c8234f6da6979a063c96c0eb32ddb55a51ce548 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 10:18:45 +0200 +Subject: [PATCH 11/19] 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 4aa6f256a07..7ccf46ae79b 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -624,26 +624,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.20.1 + + +From d8e520870c5c8943c289b3f373b1a4bcceefc174 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Wed, 16 Sep 2020 10:56:53 +0200 +Subject: [PATCH 12/19] 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 7ccf46ae79b..7994cb904b7 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -624,6 +624,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; +@@ -646,7 +647,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.20.1 + + +From 629aeb89877ca7d8aef53b5ea2c507d2f146a23b Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 17 Sep 2020 13:37:26 +0200 +Subject: [PATCH 13/19] CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon: log + warnings about unsecure configurations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +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 7994cb904b7..9972138dbde 100644 +--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c ++++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c +@@ -625,10 +625,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; +@@ -647,11 +649,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) { +@@ -665,11 +674,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.20.1 + + +From eab8661ef16856eb0926fe3426f7fe6ac870faae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 17 Sep 2020 14:57:22 +0200 +Subject: [PATCH 14/19] CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: + refactor dcesrv_netr_creds_server_step_check() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +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 693e254b051..c134e07573c 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; + +@@ -1073,19 +1074,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")); +@@ -1094,9 +1097,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.20.1 + + +From db2580705011c996a4feb01c4b6f069a4e013135 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 17 Sep 2020 14:23:16 +0200 +Subject: [PATCH 15/19] CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: + support "server require schannel:WORKSTATION$ = no" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +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 c134e07573c..3327f4bc0a0 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -1073,6 +1073,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; +@@ -1105,7 +1106,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.20.1 + + +From fa5fc293263150238755fbb8310653550f57049a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Thu, 17 Sep 2020 14:42:52 +0200 +Subject: [PATCH 16/19] CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: log + warnings about unsecure configurations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +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 3327f4bc0a0..9ef74447b84 100644 +--- a/source3/rpc_server/netlogon/srv_netlog_nt.c ++++ b/source3/rpc_server/netlogon/srv_netlog_nt.c +@@ -1074,11 +1074,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; +@@ -1106,10 +1108,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; +@@ -1122,11 +1134,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.20.1 + + +From 296a62d1589dbf33aa751e8346ba5721f6314215 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Thu, 17 Sep 2020 17:27:54 +0200 +Subject: [PATCH 17/19] 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.20.1 + + +From 3110ca45379309c55f96e97df5d6d010390cd8c6 Mon Sep 17 00:00:00 2001 +From: Gary Lockyer +Date: Fri, 18 Sep 2020 12:39:54 +1200 +Subject: [PATCH 18/19] 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 826793717e7..af9d94b99ff 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.20.1 + + +From a13ddb0fe6ddf29642976f4caff9c2391676645c Mon Sep 17 00:00:00 2001 +From: Gary Lockyer +Date: Fri, 18 Sep 2020 15:57:34 +1200 +Subject: [PATCH 19/19] 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 af9d94b99ff..c9e614fda30 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.20.1 + diff --git a/samba.spec b/samba.spec index 7447ada48664a45a327a0044c935f7a071aaf800..ffc49c0e44397b407fd751977f28a35b0aced613 100644 --- a/samba.spec +++ b/samba.spec @@ -49,7 +49,7 @@ Name: samba Version: 4.12.5 -Release: 1 +Release: 2 Summary: A suite for Linux to interoperate with Windows License: GPLv3+ and LGPLv3+ @@ -66,6 +66,8 @@ Source7: samba.pamd Source201: README.downgrade +Patch0: CVE-2020-1472.patch + BuildRequires: avahi-devel bison cups-devel dbus-devel docbook-style-xsl e2fsprogs-devel flex gawk gnupg2 gnutls-devel >= 3.4.7 gpgme-devel BuildRequires: jansson-devel krb5-devel >= %{required_mit_krb5} libacl-devel libaio-devel libarchive-devel libattr-devel BuildRequires: libcap-devel libicu-devel libcmocka-devel libnsl2-devel libtirpc-devel libuuid-devel libxslt lmdb ncurses-devel openldap-devel @@ -3085,6 +3087,12 @@ fi %endif %changelog +* Fri Sep 25 2020 liulong - 4.12.5-2 +- Type:cves +- Id:CVE-2020-1472 +- SUG:NA +- DESC:fix CVE-2020-1472 + * Thu Jul 30 2020 yuboyun - 4.12.5-1 - Type:NA - Id:NA