s3-dcerpc: avoid talloc_move on schannel creds in cli_rpc_pipe_open_schannel_with_key().
authorGünther Deschner <gd@samba.org>
Mon, 23 Aug 2010 14:02:23 +0000 (16:02 +0200)
committerGünther Deschner <gd@samba.org>
Tue, 24 Aug 2010 00:04:27 +0000 (02:04 +0200)
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
libcli/auth/proto.h
source3/rpc_client/cli_pipe.c

index 667a2fac2de369c4e2cc4360488a1d5daed0dd6d..81304764a8c5a49aaa8f6bb43b242df0969ddc0b 100644 (file)
@@ -24,6 +24,7 @@
 #include "system/time.h"
 #include "../lib/crypto/crypto.h"
 #include "libcli/auth/libcli_auth.h"
+#include "../libcli/security/dom_sid.h"
 
 static void netlogon_creds_step_crypt(struct netlogon_creds_CredentialState *creds,
                                      const struct netr_Credential *in,
@@ -202,7 +203,7 @@ struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *me
                                                                  struct netr_Credential *initial_credential,
                                                                  uint32_t negotiate_flags)
 {
-       struct netlogon_creds_CredentialState *creds = talloc(mem_ctx, struct netlogon_creds_CredentialState);
+       struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
        
        if (!creds) {
                return NULL;
@@ -454,3 +455,46 @@ 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_zero(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;
+       }
+
+       if (creds_in->sid) {
+               creds->sid = dom_sid_dup(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;
+}
index 2734db06169a466a0cc854c8accc2e922e42400d..34a0052f7a4804e547c350713c18268c7bce1ddf 100644 (file)
@@ -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
index c9b1ef65a04180e0f2a446dfc3cdb89b38c00c4e..d57bc0af60cc101d6a166faddda9e3c43cc3d9ac 100644 (file)
@@ -2383,7 +2383,7 @@ NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
        result->a_u.schannel_auth->state = SCHANNEL_STATE_START;
        result->a_u.schannel_auth->seq_num = 0;
        result->a_u.schannel_auth->initiator = true;
-       result->a_u.schannel_auth->creds = creds;
+       result->a_u.schannel_auth->creds = netlogon_creds_copy(result, creds);
 
        *presult = result;
        return NT_STATUS_OK;
@@ -3048,9 +3048,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",