1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-08 21:18:16 +03:00

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 <scabrero@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
Samuel Cabrero 2022-12-22 16:30:26 +01:00 committed by Andreas Schneider
parent 121e7b0e39
commit 25300d354c
4 changed files with 58 additions and 165 deletions

View File

@ -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,

View File

@ -289,6 +289,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
vfs_default:VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS = no
fss: sequence timeout = 1

View File

@ -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"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_SRV
@ -1059,129 +1060,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 = "<unknown>";
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;
}
/*************************************************************************
*************************************************************************/
@ -1427,11 +1305,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)) {
@ -1491,11 +1370,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)) {
@ -1642,11 +1522,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;
@ -2059,11 +1940,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;
@ -2409,11 +2291,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;
@ -2773,11 +2656,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;
@ -2876,11 +2760,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;

View File

@ -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''',