From 080ff2cd28481f39552571c30b23ec3d08811b7b Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Thu, 22 Dec 2022 16:30:26 +0100 Subject: [PATCH] CVE-2022-38023 s3:rpc_server/netlogon: Use dcesrv_netr_creds_server_step_check() After s3 and s4 rpc servers merge we can avoid duplicated code. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Samuel Cabrero Reviewed-by: Andreas Schneider (cherry picked from commit 25300d354c80995997d552581cd91dddaf4bbf48) --- librpc/rpc/server/netlogon/schannel_util.c | 6 - selftest/target/Samba3.pm | 14 ++ source3/rpc_server/netlogon/srv_netlog_nt.c | 201 +++++--------------- source3/rpc_server/wscript_build | 2 +- 4 files changed, 58 insertions(+), 165 deletions(-) diff --git a/librpc/rpc/server/netlogon/schannel_util.c b/librpc/rpc/server/netlogon/schannel_util.c index 9b2a88a2628..b14497b13ce 100644 --- a/librpc/rpc/server/netlogon/schannel_util.c +++ b/librpc/rpc/server/netlogon/schannel_util.c @@ -529,12 +529,6 @@ NTSTATUS dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, return NT_STATUS_OK; } -/* - * NOTE: The following functions are nearly identical to the ones available in - * source3/rpc_server/srv_nelog_nt.c - * The reason we keep 2 copies is that they use different structures to - * represent the auth_info and the decrpc pipes. - */ NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, const char *computer_name, diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 7e62eff98ec..ad8ef98f16a 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -288,6 +288,20 @@ sub setup_nt4_dc server require schannel:schannel11\$ = no server require schannel:torturetest\$ = no + server schannel require seal:schannel0\$ = no + server schannel require seal:schannel1\$ = no + server schannel require seal:schannel2\$ = no + server schannel require seal:schannel3\$ = no + server schannel require seal:schannel4\$ = no + server schannel require seal:schannel5\$ = no + server schannel require seal:schannel6\$ = no + server schannel require seal:schannel7\$ = no + server schannel require seal:schannel8\$ = no + server schannel require seal:schannel9\$ = no + server schannel require seal:schannel10\$ = no + server schannel require seal:schannel11\$ = no + server schannel require seal:torturetest\$ = no + fss: sequence timeout = 1 check parent directory delete on close = yes "; diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index a3853d482df..8e0ea522b6d 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -51,6 +51,7 @@ #include "libsmb/dsgetdcname.h" #include "lib/util/util_str_escape.h" #include "source3/lib/substitute.h" +#include "librpc/rpc/server/netlogon/schannel_util.h" extern userdom_struct current_user_info; @@ -1061,129 +1062,6 @@ NTSTATUS _netr_ServerAuthenticate2(struct pipes_struct *p, return _netr_ServerAuthenticate3(p, &a); } -/************************************************************************* - *************************************************************************/ - -static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, - TALLOC_CTX *mem_ctx, - const char *computer_name, - struct netr_Authenticator *received_authenticator, - struct netr_Authenticator *return_authenticator, - struct netlogon_creds_CredentialState **creds_out) -{ - struct dcesrv_call_state *dce_call = p->dce_call; - 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 = dce_call->pkt.u.request.opnum; - const char *opname = ""; - - if (creds_out != NULL) { - *creds_out = NULL; - } - - if (opnum < ndr_table_netlogon.num_calls) { - opname = ndr_table_netlogon.calls[opnum].name; - } - - dcesrv_call_auth_info(dce_call, &auth_type, NULL); - - lp_ctx = loadparm_init_s3(mem_ctx, loadparm_s3_helpers()); - if (lp_ctx == NULL) { - DEBUG(0, ("loadparm_init_s3 failed\n")); - return NT_STATUS_INTERNAL_ERROR; - } - - status = schannel_check_creds_state(mem_ctx, lp_ctx, - computer_name, received_authenticator, - return_authenticator, &creds); - talloc_unlink(mem_ctx, lp_ctx); - - 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 (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; -} - - /************************************************************************* *************************************************************************/ @@ -1429,11 +1307,12 @@ NTSTATUS _netr_ServerPasswordSet(struct pipes_struct *p, DEBUG(5,("_netr_ServerPasswordSet: %d\n", __LINE__)); become_root(); - status = netr_creds_server_step_check(p, p->mem_ctx, - r->in.computer_name, - r->in.credential, - r->out.return_authenticator, - &creds); + status = dcesrv_netr_creds_server_step_check(p->dce_call, + p->mem_ctx, + r->in.computer_name, + r->in.credential, + r->out.return_authenticator, + &creds); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { @@ -1493,11 +1372,12 @@ NTSTATUS _netr_ServerPasswordSet2(struct pipes_struct *p, bool ok; become_root(); - status = netr_creds_server_step_check(p, p->mem_ctx, - r->in.computer_name, - r->in.credential, - r->out.return_authenticator, - &creds); + status = dcesrv_netr_creds_server_step_check(p->dce_call, + p->mem_ctx, + r->in.computer_name, + r->in.credential, + r->out.return_authenticator, + &creds); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { @@ -1644,11 +1524,12 @@ NTSTATUS _netr_LogonSamLogoff(struct pipes_struct *p, struct netlogon_creds_CredentialState *creds; become_root(); - status = netr_creds_server_step_check(p, p->mem_ctx, - r->in.computer_name, - r->in.credential, - r->out.return_authenticator, - &creds); + status = dcesrv_netr_creds_server_step_check(p->dce_call, + p->mem_ctx, + r->in.computer_name, + r->in.credential, + r->out.return_authenticator, + &creds); unbecome_root(); return status; @@ -2061,11 +1942,12 @@ NTSTATUS _netr_LogonSamLogonWithFlags(struct pipes_struct *p, } become_root(); - status = netr_creds_server_step_check(p, p->mem_ctx, - r->in.computer_name, - r->in.credential, - &return_authenticator, - &creds); + status = dcesrv_netr_creds_server_step_check(p->dce_call, + p->mem_ctx, + r->in.computer_name, + r->in.credential, + &return_authenticator, + &creds); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { return status; @@ -2411,11 +2293,12 @@ NTSTATUS _netr_LogonGetCapabilities(struct pipes_struct *p, NTSTATUS status; become_root(); - status = netr_creds_server_step_check(p, p->mem_ctx, - r->in.computer_name, - r->in.credential, - r->out.return_authenticator, - &creds); + status = dcesrv_netr_creds_server_step_check(p->dce_call, + p->mem_ctx, + r->in.computer_name, + r->in.credential, + r->out.return_authenticator, + &creds); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { return status; @@ -2775,11 +2658,12 @@ NTSTATUS _netr_GetForestTrustInformation(struct pipes_struct *p, /* TODO: check server name */ become_root(); - status = netr_creds_server_step_check(p, p->mem_ctx, - r->in.computer_name, - r->in.credential, - r->out.return_authenticator, - &creds); + status = dcesrv_netr_creds_server_step_check(p->dce_call, + p->mem_ctx, + r->in.computer_name, + r->in.credential, + r->out.return_authenticator, + &creds); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { return status; @@ -2878,11 +2762,12 @@ NTSTATUS _netr_ServerGetTrustInfo(struct pipes_struct *p, /* TODO: check server name */ become_root(); - status = netr_creds_server_step_check(p, p->mem_ctx, - r->in.computer_name, - r->in.credential, - r->out.return_authenticator, - &creds); + status = dcesrv_netr_creds_server_step_check(p->dce_call, + p->mem_ctx, + r->in.computer_name, + r->in.credential, + r->out.return_authenticator, + &creds); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { return status; diff --git a/source3/rpc_server/wscript_build b/source3/rpc_server/wscript_build index 83ceca2a45c..341df41a321 100644 --- a/source3/rpc_server/wscript_build +++ b/source3/rpc_server/wscript_build @@ -174,7 +174,7 @@ bld.SAMBA3_SUBSYSTEM('RPC_NETDFS', bld.SAMBA3_SUBSYSTEM('RPC_NETLOGON', source='''netlogon/srv_netlog_nt.c''', - deps='LIBCLI_AUTH') + deps='LIBCLI_AUTH DCERPC_SERVER_NETLOGON') bld.SAMBA3_SUBSYSTEM('RPC_NTSVCS', source='''ntsvcs/srv_ntsvcs_nt.c''',