The branch, master has been updated via 9945f3e3548 CVE-2020-1472(ZeroLogon): s4 torture rpc: repeated bytes in client challenge via 4b262b03e1e CVE-2020-1472(ZeroLogon): s4 torture rpc: Test empty machine acct pwd via d1790a0b5ae CVE-2020-1472(ZeroLogon): docs-xml: document 'server require schannel:COMPUTERACCOUNT' via b8e4b0f4306 CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: log warnings about unsecure configurations via b74017d2dd1 CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: support "server require schannel:WORKSTATION$ = no" via 9ef5b63e7a1 CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: refactor dcesrv_netr_creds_server_step_check() via ca8a0098ac2 CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon: log warnings about unsecure configurations via f9b772bf286 CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon: support "server require schannel:WORKSTATION$ = no" via be8e6394990 CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon: refactor dcesrv_netr_creds_server_step_check() via 82d41977a8b CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: protect netr_ServerPasswordSet2 against unencrypted passwords via 9ec8b59bdea CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: Fix mem leak onto p->mem_ctx in error path of _netr_ServerPasswordSet2(). via d8a6e6549c1 CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon: protect netr_ServerPasswordSet2 against unencrypted passwords via d3123858fb5 CVE-2020-1472(ZeroLogon): libcli/auth: reject weak client challenges in netlogon_creds_server_init() via 53528c71ffd CVE-2020-1472(ZeroLogon): libcli/auth: add netlogon_creds_is_random_challenge() to avoid weak values via 74eb448adf7 CVE-2020-1472(ZeroLogon): s4:rpc_server:netlogon: make use of netlogon_creds_random_challenge() via caba2d8082d CVE-2020-1472(ZeroLogon): s3:rpc_server:netlogon: make use of netlogon_creds_random_challenge() via 46642fd32d9 CVE-2020-1472(ZeroLogon): libcli/auth: make use of netlogon_creds_random_challenge() in netlogon_creds_cli.c via 355efadc6a1 CVE-2020-1472(ZeroLogon): s4:torture/rpc: make use of netlogon_creds_random_challenge() via b813cdcac37 CVE-2020-1472(ZeroLogon): libcli/auth: add netlogon_creds_random_challenge() from 380938b00fb nt_printing_ads: add missing printShareName attribute when publishing printers
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 9945f3e3548657c33cc2e5ef97eedd1dfe2edf71 Author: Gary Lockyer <g...@catalyst.net.nz> Date: Fri Sep 18 15:57:34 2020 +1200 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 <g...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Fri Sep 18 14:13:17 UTC 2020 on sn-devel-184 commit 4b262b03e1e8285c399338895832a115953d3f23 Author: Gary Lockyer <g...@catalyst.net.nz> Date: Fri Sep 18 12:39:54 2020 +1200 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 <g...@catalyst.net.nz> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit d1790a0b5ae7160f6707c6c4fbf2217b251584ea Author: Stefan Metzmacher <me...@samba.org> Date: Thu Sep 17 17:27:54 2020 +0200 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 <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit b8e4b0f4306e2d0b4b7c7c443d97abf46d7f9aca Author: Günther Deschner <g...@samba.org> Date: Thu Sep 17 14:42:52 2020 +0200 CVE-2020-1472(ZeroLogon): s3:rpc_server/netlogon: log warnings about unsecure configurations BUG: https://bugzilla.samba.org/show_bug.cgi?id=14497 Pair-Programmed-With: Stefan Metzmacher <me...@samba.org> Signed-off-by: Günther Deschner <g...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit b74017d2dd15006f4bec899aa38191a3b44800e4 Author: Günther Deschner <g...@samba.org> Date: Thu Sep 17 14:23:16 2020 +0200 CVE-2020-1472(ZeroLogon): s3: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 Pair-Programmed-With: Stefan Metzmacher <me...@samba.org> Signed-off-by: Günther Deschner <g...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit 9ef5b63e7a169154401e58f7a29ed25443e5318f Author: Günther Deschner <g...@samba.org> Date: Thu Sep 17 14:57:22 2020 +0200 CVE-2020-1472(ZeroLogon): s3: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 Pair-Programmed-With: Stefan Metzmacher <me...@samba.org> Signed-off-by: Günther Deschner <g...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit ca8a0098ac207123a47b8b8f8602599d71d739db Author: Stefan Metzmacher <me...@samba.org> Date: Thu Sep 17 13:37:26 2020 +0200 CVE-2020-1472(ZeroLogon): s4:rpc_server/netlogon: log warnings about unsecure configurations 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 <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> Reviewed-by: Günther Deschner <g...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit f9b772bf286b7bde6a29cb8d7bbd241638daf5e7 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 16 10:56:53 2020 +0200 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 <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit be8e63949908d8c10d490c8cd0119df4fb917eeb Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 16 10:18:45 2020 +0200 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 <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit 82d41977a8bef426396e3e00833d55711a55f372 Author: Jeremy Allison <j...@samba.org> Date: Wed Sep 16 12:53:50 2020 -0700 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 <me...@samba.org> Signed-off-by: Jeremy Allison <j...@samba.org> Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit 9ec8b59bdea19c99099a718ff9e04cd854563e11 Author: Jeremy Allison <j...@samba.org> Date: Wed Sep 16 12:48:21 2020 -0700 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 <j...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit d8a6e6549c185daa26852d6d85f475cddfb3083a Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 16 19:20:25 2020 +0200 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 <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit d3123858fb59046e826cf2c7ec2a3839e6508624 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 16 16:17:29 2020 +0200 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 <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit 53528c71ffdb3377c4e73ac596c8507bc3898e83 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 16 16:15:26 2020 +0200 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 <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit 74eb448adf7fb638fe925eab87a2dbfe9c002cc0 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 16 16:10:53 2020 +0200 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 <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit caba2d8082d4b038aa59954b6e812612c2ecc0e1 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 16 16:10:53 2020 +0200 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 <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit 46642fd32d91b008615b859cfdf946f63b1ca0aa Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 16 16:08:38 2020 +0200 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 <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit 355efadc6a18ffaaef2e4786e35e89780b10bccc Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 16 16:07:30 2020 +0200 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 <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> commit b813cdcac377210c3ab18e0d0a0c1a76870b1d74 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 16 16:04:57 2020 +0200 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 <me...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> ----------------------------------------------------------------------- Summary of changes: docs-xml/smbdotconf/security/serverschannel.xml | 69 +++- libcli/auth/credentials.c | 44 ++- libcli/auth/netlogon_creds_cli.c | 3 +- libcli/auth/proto.h | 3 + libcli/auth/wscript_build | 2 +- source3/rpc_server/netlogon/srv_netlog_nt.c | 212 +++++++++++- source4/rpc_server/netlogon/dcerpc_netlogon.c | 175 +++++++++- source4/torture/rpc/lsa.c | 2 +- source4/torture/rpc/netlogon.c | 434 ++++++++++++++++++++---- 9 files changed, 835 insertions(+), 109 deletions(-) Changeset truncated at 500 lines: 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 @@ <description> <para> - 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). </para> <para> - This controls whether the server offers or even demands the use of the netlogon schannel. - <smbconfoption name="server schannel">no</smbconfoption> does not offer the schannel, <smbconfoption - name="server schannel">auto</smbconfoption> offers the schannel but does not enforce it, and <smbconfoption - name="server schannel">yes</smbconfoption> denies access if the client is not able to speak netlogon schannel. - This is only the case for Windows NT4 before SP4. - </para> - + Samba will complain in the log files at log level 0, + about the security problem if the option is not set to "yes". + </para> <para> - Please note that with this set to <literal>no</literal>, you will have to apply the WindowsXP - <filename>WinXP_SignOrSeal.reg</filename> registry patch found in the docs/registry subdirectory of the Samba distribution tarball. - </para> + See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497 + </para> + + <para>If you still have legacy domain members use the <smbconfoption name="server require schannel:COMPUTERACCOUNT"/> option. + </para> + + <para>This option yields precedence to the <smbconfoption name="server require schannel:COMPUTERACCOUNT"/> option.</para> + </description> <value type="default">yes</value> -<value type="example">auto</value> +</samba:parameter> + +<samba:parameter name="server require schannel:COMPUTERACCOUNT" + context="G" + type="string" + xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> +<description> + + <para>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). + </para> + + <para> + 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. + </para> + + <para> + Samba will warn in the log files at log level 5, + if a setting is still needed for the specified computer account. + </para> + + <para> + See CVE-2020-1472(ZeroLogon) https://bugzilla.samba.org/show_bug.cgi?id=14497 + </para> + + <para>This option takes precedence to the <smbconfoption name="server schannel"/> option.</para> + + <programlisting> + server require schannel:LEGACYCOMPUTER1$ = no + server require schannel:NASBOX$ = no + server require schannel:LEGACYCOMPUTER2$ = no + </programlisting> +</description> + </samba:parameter> diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index c541eeff470..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" @@ -33,6 +34,33 @@ #include <gnutls/gnutls.h> #include <gnutls/crypto.h> +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); + 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, const struct netr_Credential *in, struct netr_Credential *out) @@ -677,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; @@ -690,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/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, diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index 88f4a7c6c50..a62668f088f 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -13,6 +13,9 @@ /* 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, struct netr_LMSessionKey *key); NTSTATUS netlogon_creds_des_decrypt_LMKey(struct netlogon_creds_CredentialState *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' ) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index 2a2e2d0ac6e..c217fee9c43 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -48,6 +48,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; @@ -841,8 +842,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; @@ -1074,20 +1074,25 @@ 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 = "<unknown>"; + static bool warned_global_once = false; 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")); @@ -1096,9 +1101,97 @@ 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; + } + + /* + * 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; + 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)); + 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; } @@ -1345,9 +1438,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, @@ -1387,21 +1485,103 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, 516); } if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(creds); 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, diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 0351e2d286c..0c5ed1f0665 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -92,8 +92,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; @@ -627,26 +626,114 @@ 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; -- Samba Shared Repository