summaryrefslogtreecommitdiff
path: root/source4/rpc_server/netlogon/dcerpc_netlogon.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/rpc_server/netlogon/dcerpc_netlogon.c')
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c132
1 files changed, 35 insertions, 97 deletions
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 176246901b..d506d9192d 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -31,72 +31,9 @@
struct server_pipe_state {
struct netr_Credential client_challenge;
struct netr_Credential server_challenge;
-
- /* This is a bit (dangeroursly?) tricky:
- - The session key, computer name and domain elements are
- valid.
- - However the credentials chaining (seed, client, server etc)
- should be obtained from the database at runtime */
- struct creds_CredentialState *creds;
};
-/*
- a client has connected to the netlogon server using schannel, so we need
- to re-establish the credentials state
-*/
-static NTSTATUS netlogon_schannel_setup(struct dcesrv_call_state *dce_call)
-{
- struct server_pipe_state *state;
- NTSTATUS status;
-
- /* We want the client and server challenge zero */
- state = talloc_zero(dce_call->conn, struct server_pipe_state);
- if (state == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- status = dcerpc_schannel_creds(dce_call->conn->auth_state.gensec_security,
- state,
- &state->creds);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("getting schannel credentials failed with %s\n", nt_errstr(status)));
- talloc_free(state);
- return status;
- }
-
- dce_call->context->private = state;
-
- return NT_STATUS_OK;
-}
-
-/*
- a hook for bind on the netlogon pipe
-*/
-static NTSTATUS netlogon_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *di)
-{
- dce_call->context->private = NULL;
-
- /* if this is a schannel bind then we need to reconstruct the pipe state */
- if (dce_call->conn->auth_state.auth_info &&
- dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
- NTSTATUS status;
-
- DEBUG(5, ("schannel bind on netlogon\n"));
-
- status = netlogon_schannel_setup(dce_call);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("schannel bind on netlogon failed with %s\n", nt_errstr(status)));
- return status;
- }
- }
-
- return NT_STATUS_OK;
-}
-
-#define DCESRV_INTERFACE_NETLOGON_BIND netlogon_bind
-
static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_ServerReqChallenge *r)
{
@@ -116,8 +53,6 @@ static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALL
return NT_STATUS_NO_MEMORY;
}
- pipe_state->creds = NULL;
-
pipe_state->client_challenge = *r->in.credentials;
generate_random_buffer(pipe_state->server_challenge.data,
@@ -238,12 +173,6 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL
/* remember this session key state */
nt_status = schannel_store_session_key(mem_ctx, creds);
- if (pipe_state->creds) {
- talloc_free(pipe_state->creds);
- }
- talloc_steal(pipe_state, creds);
- pipe_state->creds = creds;
-
return nt_status;
}
@@ -302,7 +231,7 @@ static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TAL
the caller needs some of that information.
*/
-static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_state,
+static NTSTATUS netr_creds_server_step_check(const char *computer_name,
TALLOC_CTX *mem_ctx,
struct netr_Authenticator *received_authenticator,
struct netr_Authenticator *return_authenticator,
@@ -313,11 +242,6 @@ static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_stat
struct ldb_context *ldb;
int ret;
- if (!pipe_state) {
- DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
ldb = schannel_db_connect(mem_ctx);
if (!ldb) {
return NT_STATUS_ACCESS_DENIED;
@@ -333,8 +257,8 @@ static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_stat
* disconnects) we must update the database every time we
* update the structure */
- nt_status = schannel_fetch_session_key_ldb(ldb, ldb, pipe_state->creds->computer_name,
- pipe_state->creds->domain, &creds);
+ nt_status = schannel_fetch_session_key_ldb(ldb, ldb, computer_name, lp_workgroup(),
+ &creds);
if (NT_STATUS_IS_OK(nt_status)) {
nt_status = creds_server_step_check(creds,
received_authenticator,
@@ -365,12 +289,11 @@ static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_stat
static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_ServerPasswordSet *r)
{
- struct server_pipe_state *pipe_state = dce_call->context->private;
struct creds_CredentialState *creds;
struct ldb_context *sam_ctx;
NTSTATUS nt_status;
- nt_status = netr_creds_server_step_check(pipe_state, mem_ctx,
+ nt_status = netr_creds_server_step_check(r->in.computer_name, mem_ctx,
&r->in.credential, &r->out.return_authenticator,
&creds);
NT_STATUS_NOT_OK_RETURN(nt_status);
@@ -400,7 +323,6 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO
static NTSTATUS netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_ServerPasswordSet2 *r)
{
- struct server_pipe_state *pipe_state = dce_call->context->private;
struct creds_CredentialState *creds;
struct ldb_context *sam_ctx;
NTSTATUS nt_status;
@@ -410,7 +332,7 @@ static NTSTATUS netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALL
struct samr_CryptPassword password_buf;
- nt_status = netr_creds_server_step_check(pipe_state, mem_ctx,
+ nt_status = netr_creds_server_step_check(r->in.computer_name, mem_ctx,
&r->in.credential, &r->out.return_authenticator,
&creds);
NT_STATUS_NOT_OK_RETURN(nt_status);
@@ -464,15 +386,15 @@ static WERROR netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX
/*
- netr_LogonSamLogonEx
+ netr_LogonSamLogon_base
This version of the function allows other wrappers to say 'do not check the credentials'
+
+ We can't do the traditional 'wrapping' format completly, as this function must only run under schannel
*/
-static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct netr_LogonSamLogonEx *r)
+static NTSTATUS netr_LogonSamLogon_base(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct netr_LogonSamLogonEx *r, struct creds_CredentialState *creds)
{
- struct server_pipe_state *pipe_state = dce_call->context->private;
- struct creds_CredentialState *creds = pipe_state->creds;
struct auth_context *auth_context;
struct auth_usersupplied_info *user_info;
struct auth_serversupplied_info *server_info;
@@ -496,7 +418,7 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_
case 1:
case 3:
case 5:
- if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
+ if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
creds_arcfour_crypt(creds,
r->in.logon.password->lmpassword.hash,
sizeof(r->in.logon.password->lmpassword.hash));
@@ -633,6 +555,23 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_
return NT_STATUS_OK;
}
+static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct netr_LogonSamLogonEx *r)
+{
+ NTSTATUS nt_status;
+ struct creds_CredentialState *creds;
+ nt_status = schannel_fetch_session_key(mem_ctx, r->in.computer_name, lp_workgroup(), &creds);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ if (!dce_call->conn->auth_state.auth_info
+ || dce_call->conn->auth_state.auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ return netr_LogonSamLogon_base(dce_call, mem_ctx, r, creds);
+}
+
/*
netr_LogonSamLogonWithFlags
@@ -640,8 +579,8 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_
static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_LogonSamLogonWithFlags *r)
{
- struct server_pipe_state *pipe_state = dce_call->context->private;
NTSTATUS nt_status;
+ struct creds_CredentialState *creds;
struct netr_LogonSamLogonEx r2;
struct netr_Authenticator *return_authenticator;
@@ -649,21 +588,21 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call,
return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
- nt_status = netr_creds_server_step_check(pipe_state, mem_ctx,
+ nt_status = netr_creds_server_step_check(r->in.computer_name, mem_ctx,
r->in.credential, return_authenticator,
- NULL);
+ &creds);
NT_STATUS_NOT_OK_RETURN(nt_status);
ZERO_STRUCT(r2);
r2.in.server_name = r->in.server_name;
- r2.in.workstation = r->in.workstation;
+ r2.in.computer_name = r->in.computer_name;
r2.in.logon_level = r->in.logon_level;
r2.in.logon = r->in.logon;
r2.in.validation_level = r->in.validation_level;
r2.in.flags = r->in.flags;
- nt_status = netr_LogonSamLogonEx(dce_call, mem_ctx, &r2);
+ nt_status = netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
r->out.return_authenticator = return_authenticator;
r->out.validation = r2.out.validation;
@@ -685,7 +624,7 @@ static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CT
ZERO_STRUCT(r2);
r2.in.server_name = r->in.server_name;
- r2.in.workstation = r->in.workstation;
+ r2.in.computer_name = r->in.computer_name;
r2.in.credential = r->in.credential;
r2.in.return_authenticator = r->in.return_authenticator;
r2.in.logon_level = r->in.logon_level;
@@ -947,7 +886,6 @@ static NTSTATUS fill_domain_trust_info(TALLOC_CTX *mem_ctx, struct ldb_message *
static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct netr_LogonGetDomainInfo *r)
{
- struct server_pipe_state *pipe_state = dce_call->context->private;
const char * const attrs[] = { "dnsDomain", "objectSid",
"objectGUID", "flatName", "securityIdentifier",
NULL };
@@ -960,7 +898,7 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL
const char *local_domain;
- status = netr_creds_server_step_check(pipe_state, mem_ctx,
+ status = netr_creds_server_step_check(r->in.computer_name, mem_ctx,
r->in.credential,
r->out.return_authenticator,
NULL);