diff options
author | Stefan Metzmacher <metze@samba.org> | 2022-11-30 16:57:24 +0100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2022-12-14 11:39:17 +0000 |
commit | cf649bf27723eff5fe0de8fd77b9c6577eb7d4bb (patch) | |
tree | ba203afef375ea0c53be8e72ecd8ff365397c2d9 /source4 | |
parent | ff1c42ee45126824df6b4ec73f4aff8f91a406af (diff) | |
download | samba-cf649bf27723eff5fe0de8fd77b9c6577eb7d4bb.tar.gz |
CVE-2022-38023 s4:rpc_server/netlogon: split out dcesrv_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: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
(cherry picked from commit f43dc4f0bd60d4e127b714565147f82435aa4f07)
Diffstat (limited to 'source4')
-rw-r--r-- | source4/rpc_server/netlogon/dcerpc_netlogon.c | 84 |
1 files changed, 51 insertions, 33 deletions
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index ec5807ef22a..64d75c514f3 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -877,18 +877,11 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_ca return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3); } -/* - * 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. - */ -static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call, - 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 dcesrv_netr_check_schannel(struct dcesrv_call_state *dce_call, + const struct netlogon_creds_CredentialState *creds, + enum dcerpc_AuthType auth_type, + enum dcerpc_AuthLevel auth_level, + uint16_t opnum) { struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx; TALLOC_CTX *frame = talloc_stackframe(); @@ -897,15 +890,11 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc bool schannel_global_required = (schannel == true); bool schannel_required = schannel_global_required; const char *explicit_opt = NULL; - struct netlogon_creds_CredentialState *creds = NULL; int CVE_2020_1472_warn_level = lpcfg_parm_int(lp_ctx, NULL, "CVE_2020_1472", "warn_about_unused_debug_level", DBGLVL_ERR); int CVE_2020_1472_error_level = lpcfg_parm_int(lp_ctx, NULL, "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 = dce_call->pkt.u.request.opnum; const char *opname = "<unknown>"; const char *reason = "<unknown>"; @@ -913,8 +902,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc opname = ndr_table_netlogon.calls[opnum].name; } - dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); - if (auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) { reason = "WITH SEALED"; @@ -927,17 +914,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc reason = "WITHOUT"; } - nt_status = schannel_check_creds_state(mem_ctx, - lp_ctx, - computer_name, - received_authenticator, - return_authenticator, - &creds); - if (!NT_STATUS_IS_OK(nt_status)) { - ZERO_STRUCTP(return_authenticator); - return nt_status; - } - /* * We don't use lpcfg_parm_bool(), as we * need the explicit_opt pointer in order to @@ -977,7 +953,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc log_escape(frame, creds->computer_name))); } - *creds_out = creds; TALLOC_FREE(frame); return nt_status; } @@ -1011,8 +986,6 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc "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 nt_status; } @@ -1056,12 +1029,57 @@ static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dc log_escape(frame, creds->computer_name))); } - *creds_out = creds; TALLOC_FREE(frame); 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. + */ +static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call, + TALLOC_CTX *mem_ctx, + const char *computer_name, + struct netr_Authenticator *received_authenticator, + struct netr_Authenticator *return_authenticator, + struct netlogon_creds_CredentialState **creds_out) +{ + NTSTATUS nt_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; + + dcesrv_call_auth_info(dce_call, &auth_type, &auth_level); + + nt_status = schannel_check_creds_state(mem_ctx, + dce_call->conn->dce_ctx->lp_ctx, + computer_name, + received_authenticator, + return_authenticator, + &creds); + if (!NT_STATUS_IS_OK(nt_status)) { + ZERO_STRUCTP(return_authenticator); + return nt_status; + } + + nt_status = dcesrv_netr_check_schannel(dce_call, + creds, + auth_type, + auth_level, + dce_call->pkt.u.request.opnum); + if (!NT_STATUS_IS_OK(nt_status)) { + TALLOC_FREE(creds); + ZERO_STRUCTP(return_authenticator); + return nt_status; + } + + *creds_out = creds; + return NT_STATUS_OK; +} + +/* Change the machine account password for the currently connected client. Supplies only the NT#. */ |