From 8eb981c90a6094b15d4b71cc14fee4f23c713cf8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 3 Jan 2005 06:23:02 +0000 Subject: r4499: Almost make our Samba4 server pass the RPC-SAMLOGON torture test. I just need to fix a couple of NTLMv2 issues before we can fully pass, and put this in test_rpc.sh, as a 'should pass' test. Andrew Bartlett (This used to be commit 4b52409e385366d87724bb79f4fad4803e8ecfec) --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 140 +++++++++++++++----------- source4/rpc_server/netlogon/schannel_state.c | 13 ++- 2 files changed, 96 insertions(+), 57 deletions(-) (limited to 'source4/rpc_server') diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 422aa626ed..167c4e8ceb 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -317,12 +317,17 @@ static NTSTATUS netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TAL } -static BOOL netr_creds_server_step_check(struct server_pipe_state *pipe_state, - struct netr_Authenticator *received_authenticator, - struct netr_Authenticator *return_authenticator) +static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_state, + struct netr_Authenticator *received_authenticator, + struct netr_Authenticator *return_authenticator) { + if (!pipe_state) { + DEBUG(1, ("No challenge requested by client, cannot authenticate\n")); + return NT_STATUS_ACCESS_DENIED; + } + if (!pipe_state->authenticated) { - return False; + return NT_STATUS_ACCESS_DENIED; } return creds_server_step_check(pipe_state->creds, received_authenticator, @@ -351,13 +356,9 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO const char **domain_attrs = attrs; ZERO_STRUCT(mod); - if (!pipe_state) { - DEBUG(1, ("No challenge requested by client, cannot authenticate\n")); - return NT_STATUS_ACCESS_DENIED; - } - - if (!netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator)) { - return NT_STATUS_ACCESS_DENIED; + nt_status = netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator); + if (NT_STATUS_IS_OK(nt_status)) { + return nt_status; } sam_ctx = samdb_connect(mem_ctx); @@ -461,9 +462,10 @@ static WERROR netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX /* netr_LogonSamLogonWithFlags + This version of the function allows other wrappers to say 'do not check the credentials' */ -static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct netr_LogonSamLogonWithFlags *r) +static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct netr_LogonSamLogonEx *r) { struct server_pipe_state *pipe_state = dce_call->conn->private; @@ -478,30 +480,21 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, struct netr_SamInfo3 *sam3; struct netr_SamInfo6 *sam6; - if (!pipe_state) { - DEBUG(1, ("No challenge requested by client, cannot authenticate\n")); - return NT_STATUS_ACCESS_DENIED; - } - - r->out.return_authenticator = talloc_p(mem_ctx, struct netr_Authenticator); - if (!r->out.return_authenticator) { - return NT_STATUS_NO_MEMORY; - } - - if (!netr_creds_server_step_check(pipe_state, r->in.credential, r->out.return_authenticator)) { - return NT_STATUS_ACCESS_DENIED; - } - switch (r->in.logon_level) { case 1: case 3: case 5: - creds_arcfour_crypt(pipe_state->creds, - r->in.logon.password->lmpassword.hash, - sizeof(r->in.logon.password->lmpassword.hash)); - creds_arcfour_crypt(pipe_state->creds, - r->in.logon.password->ntpassword.hash, - sizeof(r->in.logon.password->ntpassword.hash)); + if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { + creds_arcfour_crypt(pipe_state->creds, + r->in.logon.password->lmpassword.hash, + sizeof(r->in.logon.password->lmpassword.hash)); + creds_arcfour_crypt(pipe_state->creds, + r->in.logon.password->ntpassword.hash, + sizeof(r->in.logon.password->ntpassword.hash)); + } else { + creds_des_decrypt(pipe_state->creds, &r->in.logon.password->lmpassword); + creds_des_decrypt(pipe_state->creds, &r->in.logon.password->ntpassword); + } nt_status = make_auth_context_subsystem(pipe_state, &auth_context); if (!NT_STATUS_IS_OK(nt_status)) { @@ -600,9 +593,13 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, if ((r->in.validation_level != 6) && memcmp(sam->key.key, zeros, sizeof(sam->key.key)) != 0) { - creds_arcfour_crypt(pipe_state->creds, - sam->key.key, - sizeof(sam->key.key)); + + /* This key is sent unencrypted without the ARCFOUR flag set */ + if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { + creds_arcfour_crypt(pipe_state->creds, + sam->key.key, + sizeof(sam->key.key)); + } } if (server_info->lm_session_key.length == sizeof(sam->LMSessKey.key)) { @@ -617,9 +614,14 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, if ((r->in.validation_level != 6) && memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) { - creds_arcfour_crypt(pipe_state->creds, - sam->LMSessKey.key, - sizeof(sam->LMSessKey.key)); + if (pipe_state->creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { + creds_arcfour_crypt(pipe_state->creds, + sam->LMSessKey.key, + sizeof(sam->LMSessKey.key)); + } else { + creds_des_encrypt_LMKey(pipe_state->creds, + &sam->LMSessKey); + } } switch (r->in.validation_level) { @@ -656,6 +658,45 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, return NT_STATUS_OK; } +/* + netr_LogonSamLogonWithFlags + +*/ +static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, + struct netr_LogonSamLogonWithFlags *r) +{ + NTSTATUS nt_status; + struct netr_LogonSamLogonEx r2; + + struct server_pipe_state *pipe_state = dce_call->conn->private; + + r->out.return_authenticator = talloc_p(mem_ctx, struct netr_Authenticator); + if (!r->out.return_authenticator) { + return NT_STATUS_NO_MEMORY; + } + + nt_status = netr_creds_server_step_check(pipe_state, r->in.credential, r->out.return_authenticator); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + ZERO_STRUCT(r2); + + r2.in.server_name = r->in.server_name; + r2.in.workstation = r->in.workstation; + 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); + + r->out.validation = r2.out.validation; + r->out.authoritative = r2.out.authoritative; + + return nt_status; +} + /* netr_LogonSamLogon */ @@ -940,13 +981,10 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL int ret1, ret2, i; NTSTATUS status; - if (!pipe_state) { - return NT_STATUS_ACCESS_DENIED; - } - - if (!netr_creds_server_step_check(pipe_state, - r->in.credential, r->out.credential)) { - return NT_STATUS_ACCESS_DENIED; + status = netr_creds_server_step_check(pipe_state, + r->in.credential, r->out.credential); + if (!NT_STATUS_IS_OK(status)) { + return status; } sam_ctx = samdb_connect(mem_ctx); @@ -1133,16 +1171,6 @@ static WERROR netr_DSRGETDCSITECOVERAGEW(struct dcesrv_call_state *dce_call, TAL } -/* - netr_LogonSamLogonEx -*/ -static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, - struct netr_LogonSamLogonEx *r) -{ - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); -} - - /* netr_DsrEnumerateDomainTrusts */ diff --git a/source4/rpc_server/netlogon/schannel_state.c b/source4/rpc_server/netlogon/schannel_state.c index 564564e8c2..7dc60a1617 100644 --- a/source4/rpc_server/netlogon/schannel_state.c +++ b/source4/rpc_server/netlogon/schannel_state.c @@ -61,7 +61,8 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx, struct ldb_wrap *ldb; struct ldb_message *msg; struct ldb_val val, seed; - char *s = NULL; + char *s; + char *f; time_t expiry = time(NULL) + SCHANNEL_CREDENTIALS_EXPIRY; int ret; @@ -77,6 +78,13 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } + f = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->negotiate_flags); + + if (f == NULL) { + talloc_free(ldb); + return NT_STATUS_NO_MEMORY; + } + msg = ldb_msg_new(mem_ctx); if (msg == NULL) { talloc_free(ldb); @@ -99,6 +107,7 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx, ldb_msg_add_value(ldb->ldb, msg, "sessionKey", &val); ldb_msg_add_value(ldb->ldb, msg, "seed", &seed); ldb_msg_add_string(ldb->ldb, msg, "expiry", s); + ldb_msg_add_string(ldb->ldb, msg, "negotiateFlags", f); ldb_delete(ldb->ldb, msg->dn); @@ -180,6 +189,8 @@ NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx, memcpy((*creds)->seed.data, val->data, 8); + (*creds)->negotiate_flags = ldb_msg_find_int(res[0], "negotiateFlags", 0); + talloc_free(ldb); return NT_STATUS_OK; -- cgit