From 24d91b96790628ba864c67cca0b97b95ad7f9555 Mon Sep 17 00:00:00 2001 From: Samuel Cabrero Date: Thu, 22 Dec 2022 11:42:51 +0100 Subject: [PATCH 35/40] CVE-2022-38023 s3:rpc_server/netlogon: split out netr_check_schannel() function This will allow us to reuse the function in other places. As it will also get some additional checks soon. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15240 Signed-off-by: Samuel Cabrero Conflict: NA Reference: https://attachments.samba.org/attachment.cgi?id=17736 --- source3/rpc_server/netlogon/srv_netlog_nt.c | 107 ++++++++++++-------- 1 file changed, 62 insertions(+), 45 deletions(-) diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c index c9401499a9b..b254ca72a48 100644 --- a/source3/rpc_server/netlogon/srv_netlog_nt.c +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c @@ -1063,53 +1063,30 @@ NTSTATUS _netr_ServerAuthenticate2(struct pipes_struct *p, /************************************************************************* *************************************************************************/ -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) +static NTSTATUS netr_check_schannel(struct pipes_struct *p, + const struct netlogon_creds_CredentialState *creds, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, + uint16_t opnum) { TALLOC_CTX *frame = talloc_stackframe(); 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; - int CVE_2020_1472_warn_level = DBGLVL_ERR; - int CVE_2020_1472_error_level = DBGLVL_ERR; + int CVE_2020_1472_warn_level = lp_parm_int(GLOBAL_SECTION_SNUM, + "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR); + int CVE_2020_1472_error_level = lp_parm_int(GLOBAL_SECTION_SNUM, + "CVE_2020_1472", "error_debug_level", DBGLVL_ERR); unsigned int dbg_lvl = DBGLVL_DEBUG; - enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; - enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; - uint16_t opnum = p->opnum; const char *opname = ""; const char *reason = ""; static bool warned_global_once = false; - if (creds_out != NULL) { - *creds_out = NULL; - } - if (opnum < ndr_table_netlogon.num_calls) { opname = ndr_table_netlogon.calls[opnum].name; } - auth_type = p->auth.auth_type; - auth_level = p->auth.auth_level; - - lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers()); - if (lp_ctx == NULL) { - DEBUG(0, ("loadparm_init_s3 failed\n")); - TALLOC_FREE(frame); - return NT_STATUS_INTERNAL_ERROR; - } - - CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL, - "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR); - CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL, - "CVE_2020_1472", "error_debug_level", DBGLVL_ERR); - if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { reason = "WITH SEALED"; @@ -1122,15 +1099,6 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, reason = "WITHOUT"; } - status = schannel_check_creds_state(mem_ctx, lp_ctx, - computer_name, received_authenticator, - return_authenticator, &creds); - if (!NT_STATUS_IS_OK(status)) { - ZERO_STRUCTP(return_authenticator); - TALLOC_FREE(frame); - return status; - } - /* * We don't use lp_parm_bool(), as we * need the explicit_opt pointer in order to @@ -1171,7 +1139,6 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, log_escape(frame, creds->computer_name))); } - *creds_out = creds; TALLOC_FREE(frame); return status; } @@ -1205,8 +1172,6 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, "might be needed for a legacy client.\n", log_escape(frame, creds->account_name))); } - TALLOC_FREE(creds); - ZERO_STRUCTP(return_authenticator); TALLOC_FREE(frame); return status; } @@ -1260,11 +1225,63 @@ static NTSTATUS netr_creds_server_step_check(struct pipes_struct *p, log_escape(frame, creds->computer_name))); } - *creds_out = creds; TALLOC_FREE(frame); return NT_STATUS_OK; } +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 loadparm_context *lp_ctx = NULL; + NTSTATUS status; + struct netlogon_creds_CredentialState *creds = NULL; + enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE; + enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE; + uint16_t opnum = p->opnum; + + if (creds_out != NULL) { + *creds_out = NULL; + } + + auth_type = p->auth.auth_type; + auth_level = p->auth.auth_level; + + 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_FREE(lp_ctx); + if (!NT_STATUS_IS_OK(status)) { + ZERO_STRUCTP(return_authenticator); + return status; + } + + status = netr_check_schannel(p, + creds, + auth_type, + auth_level, + opnum); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(creds); + ZERO_STRUCTP(return_authenticator); + return status; + } + + *creds_out = creds; + return NT_STATUS_OK; +} /************************************************************************* *************************************************************************/ -- 2.39.0