1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +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>
(cherry picked from commit 25300d354c)
This commit is contained in:
Samuel Cabrero 2022-12-22 16:30:26 +01:00 committed by Jule Anger
parent 0d27e4b459
commit 080ff2cd28
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

@ -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
";

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"
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 = "<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;
}
/*************************************************************************
*************************************************************************/
@ -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;

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