#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;
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>";
- 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;
- }
-
- 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 (!schannel_global_required && !warned_global_once) {
- /*
- * We want admins to notice their misconfiguration!
- */
- DBG_ERR("CVE-2020-1472(ZeroLogon): "
- "Please configure 'server schannel = yes', "
- "See https://bugzilla.samba.org/show_bug.cgi?id=14497\n");
- warned_global_once = true;
- }
-
- 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;
-}
-
-
/*************************************************************************
*************************************************************************/
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)) {
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)) {
- const char *computer_name = "<unknown>";
-
- if (creds && creds->computer_name) {
- computer_name = creds->computer_name;
- }
- DEBUG(2,("_netr_ServerPasswordSet2: netlogon_creds_server_step "
- "failed. Rejecting auth request from client %s machine account %s\n",
- r->in.computer_name, computer_name));
+ DBG_NOTICE("netlogon_creds_server_step failed. "
+ "Rejecting auth request from client %s\n",
+ r->in.computer_name);
TALLOC_FREE(creds);
return status;
}
DBG_NOTICE("Server Password Set2 by remote "
"machine:[%s] on account [%s]\n",
r->in.computer_name,
- creds->computer_name);
+ creds->computer_name != NULL ?
+ creds->computer_name : "<unknown>");
memcpy(password_buf.data, r->in.new_password->data, 512);
SIVAL(password_buf.data, 512, r->in.new_password->length);
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;
struct auth_serversupplied_info *server_info = NULL;
struct auth_context *auth_context = NULL;
const char *fn;
+ 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;
+
+ dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
#ifdef DEBUG_PASSWORD
logon = netlogon_creds_shallow_copy_logon(p->mem_ctx,
}
#endif
- switch (dce_call->pkt.u.request.opnum) {
+ switch (opnum) {
case NDR_NETR_LOGONSAMLOGON:
fn = "_netr_LogonSamLogon";
+ /*
+ * Already called netr_check_schannel() via
+ * netr_creds_server_step_check()
+ */
break;
case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
fn = "_netr_LogonSamLogonWithFlags";
+ /*
+ * Already called netr_check_schannel() via
+ * netr_creds_server_step_check()
+ */
break;
case NDR_NETR_LOGONSAMLOGONEX:
fn = "_netr_LogonSamLogonEx";
+
+ if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ status = dcesrv_netr_check_schannel(p->dce_call,
+ creds,
+ auth_type,
+ auth_level,
+ opnum);
+ if (NT_STATUS_IS_ERR(status)) {
+ return status;
+ }
+
break;
default:
return NT_STATUS_INTERNAL_ERROR;
r->out.validation->sam3);
break;
case 6: {
- enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
-
- dcesrv_call_auth_info(dce_call, NULL, &auth_level);
-
/* Only allow this if the pipe is protected. */
if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
DEBUG(0,("netr_Validation6: client %s not using privacy for netlogon\n",
}
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;
NTSTATUS _netr_LogonSamLogonEx(struct pipes_struct *p,
struct netr_LogonSamLogonEx *r)
{
- struct dcesrv_call_state *dce_call = p->dce_call;
- enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
NTSTATUS status;
struct netlogon_creds_CredentialState *creds = NULL;
struct loadparm_context *lp_ctx;
return status;
}
- /* Only allow this if the pipe is protected. */
-
- dcesrv_call_auth_info(dce_call, &auth_type, NULL);
-
- if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
- DEBUG(0,("_netr_LogonSamLogonEx: client %s not using schannel for netlogon\n",
- get_remote_machine_name() ));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
lp_ctx = loadparm_init_s3(p->mem_ctx, loadparm_s3_helpers());
if (lp_ctx == NULL) {
DEBUG(0, ("loadparm_init_s3 failed\n"));
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;
/* 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;
/* 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;
return NT_STATUS_NOT_IMPLEMENTED;
}
+/*
+ * Define the bind function that will be used by ndr_netlogon_scompat.c,
+ * included at the bottom of this file.
+ */
+#define DCESRV_INTERFACE_NETLOGON_BIND(context, iface) \
+ dcesrv_interface_netlogon_bind(context, iface)
+
+static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context *context,
+ const struct dcesrv_interface *iface)
+{
+ struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
+ int schannel = lpcfg_server_schannel(lp_ctx);
+ bool schannel_global_required = (schannel == true);
+ static bool warned_global_schannel_once = false;
+
+ if (!schannel_global_required && !warned_global_schannel_once) {
+ /*
+ * We want admins to notice their misconfiguration!
+ */
+ D_ERR("CVE-2020-1472(ZeroLogon): "
+ "Please configure 'server schannel = yes' (the default), "
+ "See https://bugzilla.samba.org/show_bug.cgi?id=14497\n");
+ warned_global_schannel_once = true;
+ }
+
+ return NT_STATUS_OK;
+}
+
/* include the generated boilerplate */
#include "librpc/gen_ndr/ndr_netlogon_scompat.c"