diff options
-rw-r--r-- | source4/libcli/auth/credentials.c | 8 | ||||
-rw-r--r-- | source4/libcli/auth/credentials.h | 3 | ||||
-rw-r--r-- | source4/rpc_server/netlogon/dcerpc_netlogon.c | 62 | ||||
-rw-r--r-- | source4/rpc_server/netlogon/schannel_state.c | 22 |
4 files changed, 46 insertions, 49 deletions
diff --git a/source4/libcli/auth/credentials.c b/source4/libcli/auth/credentials.c index 8cae71180c..18ce6fec1b 100644 --- a/source4/libcli/auth/credentials.c +++ b/source4/libcli/auth/credentials.c @@ -292,13 +292,17 @@ BOOL creds_server_check(const struct creds_CredentialState *creds, } NTSTATUS creds_server_step_check(struct creds_CredentialState *creds, - struct netr_Authenticator *received_authenticator, - struct netr_Authenticator *return_authenticator) + struct netr_Authenticator *received_authenticator, + struct netr_Authenticator *return_authenticator) { if (!received_authenticator || !return_authenticator) { return NT_STATUS_INVALID_PARAMETER; } + if (!creds) { + return NT_STATUS_ACCESS_DENIED; + } + /* TODO: this may allow the a replay attack on a non-signed connection. Should we check that this is increasing? */ creds->sequence = received_authenticator->timestamp; diff --git a/source4/libcli/auth/credentials.h b/source4/libcli/auth/credentials.h index 30114fe7fa..01206bc282 100644 --- a/source4/libcli/auth/credentials.h +++ b/source4/libcli/auth/credentials.h @@ -27,6 +27,9 @@ struct creds_CredentialState { struct netr_Credential seed; struct netr_Credential client; struct netr_Credential server; + uint16_t secure_channel_type; + char *computer_name; + char *account_name; }; diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index afb066f4ee..ab67a2595e 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -32,11 +32,6 @@ struct server_pipe_state { struct netr_Credential client_challenge; struct netr_Credential server_challenge; - BOOL authenticated; - char *account_name; - char *computer_name; /* for logging only */ - uint32_t acct_flags; - uint16_t sec_chan_type; struct creds_CredentialState *creds; }; @@ -55,7 +50,6 @@ static NTSTATUS netlogon_schannel_setup(struct dcesrv_call_state *dce_call) return NT_STATUS_NO_MEMORY; } ZERO_STRUCTP(state); - state->authenticated = True; if (dce_call->conn->auth_state.session_info == NULL) { talloc_free(state); @@ -102,16 +96,7 @@ static NTSTATUS netlogon_bind(struct dcesrv_call_state *dce_call, const struct d return NT_STATUS_OK; } -/* this function is called when the client disconnects the endpoint */ -static void netlogon_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *di) -{ - struct server_pipe_state *pipe_state = context->private; - talloc_free(pipe_state); - context->private = NULL; -} - #define DCESRV_INTERFACE_NETLOGON_BIND netlogon_bind -#define DCESRV_INTERFACE_NETLOGON_UNBIND netlogon_unbind static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct netr_ServerReqChallenge *r) @@ -132,10 +117,7 @@ static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALL return NT_STATUS_NO_MEMORY; } - pipe_state->authenticated = False; pipe_state->creds = NULL; - pipe_state->account_name = NULL; - pipe_state->computer_name = NULL; pipe_state->client_challenge = *r->in.credentials; @@ -220,8 +202,6 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL return NT_STATUS_ACCESS_DENIED; } - pipe_state->acct_flags = acct_flags; - pipe_state->sec_chan_type = r->in.secure_channel_type; *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0], "objectSid", 0); @@ -230,11 +210,12 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL return NT_STATUS_ACCESS_DENIED; } + if (pipe_state->creds) { + talloc_free(pipe_state->creds); + } + pipe_state->creds = talloc_p(pipe_state, struct creds_CredentialState); if (!pipe_state->creds) { - pipe_state->creds = talloc_p(pipe_state, struct creds_CredentialState); - if (!pipe_state->creds) { - return NT_STATUS_NO_MEMORY; - } + return NT_STATUS_NO_MEMORY; } creds_server_init(pipe_state->creds, &pipe_state->client_challenge, @@ -243,27 +224,19 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL *r->in.negotiate_flags); if (!creds_server_check(pipe_state->creds, r->in.credentials)) { + talloc_free(pipe_state->creds); + pipe_state->creds = NULL; return NT_STATUS_ACCESS_DENIED; } - pipe_state->authenticated = True; - - if (pipe_state->account_name) { - /* We don't want a memory leak on this long-lived talloc context */ - talloc_free(pipe_state->account_name); - } - - pipe_state->account_name = talloc_strdup(pipe_state, r->in.account_name); + pipe_state->creds->account_name = talloc_reference(pipe_state->creds, r->in.account_name); - if (pipe_state->computer_name) { - /* We don't want a memory leak on this long-lived talloc context */ - talloc_free(pipe_state->computer_name); - } + pipe_state->creds->computer_name = talloc_reference(pipe_state->creds, r->in.computer_name); - pipe_state->computer_name = talloc_strdup(pipe_state, r->in.computer_name); + pipe_state->creds->secure_channel_type = r->in.secure_channel_type; /* remember this session key state */ - nt_status = schannel_store_session_key(mem_ctx, pipe_state->computer_name, pipe_state->creds); + nt_status = schannel_store_session_key(mem_ctx, pipe_state->creds); return nt_status; } @@ -323,9 +296,6 @@ static NTSTATUS netr_creds_server_step_check(struct server_pipe_state *pipe_stat return NT_STATUS_ACCESS_DENIED; } - if (!pipe_state->authenticated) { - return NT_STATUS_ACCESS_DENIED; - } return creds_server_step_check(pipe_state->creds, received_authenticator, return_authenticator); @@ -365,17 +335,17 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO /* pull the user attributes */ num_records = samdb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs, "(&(sAMAccountName=%s)(objectclass=user))", - pipe_state->account_name); + pipe_state->creds->account_name); if (num_records == 0) { DEBUG(3,("Couldn't find user [%s] in samdb.\n", - pipe_state->account_name)); + pipe_state->creds->account_name)); return NT_STATUS_NO_SUCH_USER; } if (num_records > 1) { DEBUG(0,("Found %d records matching user [%s]\n", num_records, - pipe_state->account_name)); + pipe_state->creds->account_name)); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -643,6 +613,9 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_ r->out.authoritative = 1; + /* TODO: Describe and deal with these flags */ + r->out.flags = 0; + return NT_STATUS_OK; } @@ -681,6 +654,7 @@ static NTSTATUS netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, r->out.validation = r2.out.validation; r->out.authoritative = r2.out.authoritative; + r->out.flags = r2.out.flags; return nt_status; } diff --git a/source4/rpc_server/netlogon/schannel_state.c b/source4/rpc_server/netlogon/schannel_state.c index 7dc60a1617..56f7152c14 100644 --- a/source4/rpc_server/netlogon/schannel_state.c +++ b/source4/rpc_server/netlogon/schannel_state.c @@ -55,7 +55,6 @@ static struct ldb_wrap *schannel_db_connect(TALLOC_CTX *mem_ctx) use a simple ldb structure */ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx, - const char *computer_name, struct creds_CredentialState *creds) { struct ldb_wrap *ldb; @@ -63,6 +62,7 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx, struct ldb_val val, seed; char *s; char *f; + char *sct; time_t expiry = time(NULL) + SCHANNEL_CREDENTIALS_EXPIRY; int ret; @@ -85,13 +85,20 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } + sct = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->secure_channel_type); + + if (sct == NULL) { + talloc_free(ldb); + return NT_STATUS_NO_MEMORY; + } + msg = ldb_msg_new(mem_ctx); if (msg == NULL) { talloc_free(ldb); return NT_STATUS_NO_MEMORY; } - msg->dn = talloc_strdup(msg, computer_name); + msg->dn = talloc_asprintf(msg, "computerName=%s", creds->computer_name); if (msg->dn == NULL) { talloc_free(ldb); talloc_free(msg); @@ -108,6 +115,9 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx, 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_msg_add_string(ldb->ldb, msg, "secureChannelType", sct); + ldb_msg_add_string(ldb->ldb, msg, "accountName", creds->account_name); + ldb_msg_add_string(ldb->ldb, msg, "computerName", creds->computer_name); ldb_delete(ldb->ldb, msg->dn); @@ -154,7 +164,7 @@ NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - expr = talloc_asprintf(mem_ctx, "(dn=%s)", computer_name); + expr = talloc_asprintf(mem_ctx, "(dn=computerName=%s)", computer_name); if (expr == NULL) { talloc_free(ldb); return NT_STATUS_NO_MEMORY; @@ -191,6 +201,12 @@ NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx, (*creds)->negotiate_flags = ldb_msg_find_int(res[0], "negotiateFlags", 0); + (*creds)->secure_channel_type = ldb_msg_find_int(res[0], "secureChannelType", 0); + + (*creds)->account_name = talloc_reference(*creds, ldb_msg_find_string(res[0], "accountName", NULL)); + + (*creds)->computer_name = talloc_reference(*creds, ldb_msg_find_string(res[0], "computerName", NULL)); + talloc_free(ldb); return NT_STATUS_OK; |