From b54d2f8e9698d84ff82ef32f6cd154a30c37a62f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Mon, 23 Aug 2010 14:02:23 +0200 Subject: [PATCH 1/2] s3-dcerpc: avoid talloc_move on schannel creds in cli_rpc_pipe_open_schannel_with ... s3-dcerpc: avoid talloc_move on schannel creds in cli_rpc_pipe_open_schannel_with_key(). Initially, the schannel creds were talloc memduped, then, during the netlogon creds client merge (baf7274fed2f1ae7a9e3a57160bf5471566e636c) they were first talloc_referenced and then later (53765c81f726a8c056cc4e57004592dd489975c9) talloc_moved. The issue with using talloc_move here is that users of that function in winbind will only be able to have two schanneled connections, as the cached schannel credentials pointer from the netlogon pipe will be set to NULL. Do a deep copy of the struct instead. Guenther --- libcli/auth/credentials.c | 41 +++++++++++++++++++++++++++++++++++++++++ libcli/auth/proto.h | 2 ++ source3/rpc_client/cli_pipe.c | 8 ++++++-- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/libcli/auth/credentials.c b/libcli/auth/credentials.c index 87d1866..30fe407 100644 --- a/libcli/auth/credentials.c +++ b/libcli/auth/credentials.c @@ -453,3 +453,44 @@ void netlogon_creds_decrypt_samlogon(struct netlogon_creds_CredentialState *cred } } +/* + copy a netlogon_creds_CredentialState struct +*/ + +struct netlogon_creds_CredentialState *netlogon_creds_copy(TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState *creds_in) +{ + struct netlogon_creds_CredentialState *creds = talloc(mem_ctx, struct netlogon_creds_CredentialState); + + if (!creds) { + return NULL; + } + + creds->sequence = creds_in->sequence; + creds->negotiate_flags = creds_in->negotiate_flags; + creds->secure_channel_type = creds_in->secure_channel_type; + + creds->computer_name = talloc_strdup(creds, creds_in->computer_name); + if (!creds->computer_name) { + talloc_free(creds); + return NULL; + } + creds->account_name = talloc_strdup(creds, creds_in->account_name); + if (!creds->account_name) { + talloc_free(creds); + return NULL; + } + + creds->sid = sid_dup_talloc(creds, creds_in->sid); + if (!creds->sid) { + talloc_free(creds); + return NULL; + } + + memcpy(creds->session_key, creds_in->session_key, sizeof(creds->session_key)); + memcpy(creds->seed.data, creds_in->seed.data, sizeof(creds->seed.data)); + memcpy(creds->client.data, creds_in->client.data, sizeof(creds->client.data)); + memcpy(creds->server.data, creds_in->server.data, sizeof(creds->server.data)); + + return creds; +} diff --git a/libcli/auth/proto.h b/libcli/auth/proto.h index e09cdee..c3878f5 100644 --- a/libcli/auth/proto.h +++ b/libcli/auth/proto.h @@ -35,6 +35,8 @@ void netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState * struct netr_Authenticator *next); bool netlogon_creds_client_check(struct netlogon_creds_CredentialState *creds, const struct netr_Credential *received_credentials); +struct netlogon_creds_CredentialState *netlogon_creds_copy(TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState *creds_in); /***************************************************************** The above functions are common to the client and server interface diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index ee60c1d..535a4cb 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -4044,9 +4044,13 @@ NTSTATUS cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, /* * The credentials on a new netlogon pipe are the ones we are passed - * in - reference them in + * in - copy them over */ - result->dc = talloc_move(result, pdc); + result->dc = netlogon_creds_copy(result, *pdc); + if (result->dc == NULL) { + TALLOC_FREE(result); + return NT_STATUS_NO_MEMORY; + } DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " "for domain %s and bound using schannel.\n", -- 1.7.1