s3:ntlmssp Use a TALLOC_CTX for ntlmssp_sign_packet() and ntlmssp_seal_packet()
authorAndrew Bartlett <abartlet@samba.org>
Tue, 25 May 2010 10:55:40 +0000 (20:55 +1000)
committerGünther Deschner <gd@samba.org>
Mon, 31 May 2010 13:11:27 +0000 (15:11 +0200)
This ensures the results can't be easily left to leak.

Andrew Bartlett

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Günther Deschner <gd@samba.org>
source3/auth/auth_ntlmssp.c
source3/include/proto.h
source3/libads/sasl.c
source3/libsmb/ntlmssp_sign.c
source3/libsmb/smb_seal.c
source3/rpc_client/cli_pipe.c
source3/rpc_server/srv_pipe.c

index b455bc505f9fb4a09238c2f565841904f346bce8..e0e0003f9dc944c5d4e7eefe009b85b7ff87c2af 100644 (file)
@@ -31,11 +31,12 @@ struct auth_ntlmssp_state {
 };
 
 NTSTATUS auth_ntlmssp_sign_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+                                 TALLOC_CTX *sig_mem_ctx,
                                  const uint8_t *data, size_t length,
                                  const uint8_t *whole_pdu, size_t pdu_length,
                                  DATA_BLOB *sig)
 {
-       return ntlmssp_sign_packet(auth_ntlmssp_state->ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
+       return ntlmssp_sign_packet(auth_ntlmssp_state->ntlmssp_state, sig_mem_ctx, data, length, whole_pdu, pdu_length, sig);
 }
 
 NTSTATUS auth_ntlmssp_check_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
@@ -47,11 +48,12 @@ NTSTATUS auth_ntlmssp_check_packet(struct auth_ntlmssp_state *auth_ntlmssp_state
 }
 
 NTSTATUS auth_ntlmssp_seal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+                                 TALLOC_CTX *sig_mem_ctx,
                                  uint8_t *data, size_t length,
                                  const uint8_t *whole_pdu, size_t pdu_length,
                                  DATA_BLOB *sig)
 {
-       return ntlmssp_seal_packet(auth_ntlmssp_state->ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
+       return ntlmssp_seal_packet(auth_ntlmssp_state->ntlmssp_state, sig_mem_ctx, data, length, whole_pdu, pdu_length, sig);
 }
 
 NTSTATUS auth_ntlmssp_unseal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
index d479edbc9f27744e50ca23af2533eca8bfdf8a96..472e1793cafbf778a9d3bd069c63c25f341e428f 100644 (file)
@@ -67,6 +67,7 @@ void auth_ntlmssp_end(struct auth_ntlmssp_state **auth_ntlmssp_state);
 NTSTATUS auth_ntlmssp_update(struct auth_ntlmssp_state *auth_ntlmssp_state,
                             const DATA_BLOB request, DATA_BLOB *reply) ;
 NTSTATUS auth_ntlmssp_sign_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+                                 TALLOC_CTX *sig_mem_ctx,
                                  const uint8_t *data, size_t length,
                                  const uint8_t *whole_pdu, size_t pdu_length,
                                  DATA_BLOB *sig);
@@ -75,6 +76,7 @@ NTSTATUS auth_ntlmssp_check_packet(struct auth_ntlmssp_state *auth_ntlmssp_state
                                   const uint8_t *whole_pdu, size_t pdu_length,
                                   const DATA_BLOB *sig) ;
 NTSTATUS auth_ntlmssp_seal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+                                 TALLOC_CTX *sig_mem_ctx,
                                  uint8_t *data, size_t length,
                                  const uint8_t *whole_pdu, size_t pdu_length,
                                  DATA_BLOB *sig);
@@ -3162,6 +3164,7 @@ NTSTATUS ntlmssp_client_start(TALLOC_CTX *mem_ctx,
 /* The following definitions come from libsmb/ntlmssp_sign.c  */
 
 NTSTATUS ntlmssp_sign_packet(struct ntlmssp_state *ntlmssp_state,
+                            TALLOC_CTX *sig_mem_ctx,
                             const uint8_t *data, size_t length,
                             const uint8_t *whole_pdu, size_t pdu_length,
                             DATA_BLOB *sig);
@@ -3170,6 +3173,7 @@ NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
                              const uint8_t *whole_pdu, size_t pdu_length,
                              const DATA_BLOB *sig) ;
 NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state,
+                            TALLOC_CTX *sig_mem_ctx,
                             uint8_t *data, size_t length,
                             const uint8_t *whole_pdu, size_t pdu_length,
                             DATA_BLOB *sig);
index 8f7f6c11dfe47049aa9d7d954d15bc7c065c1a82..04b9a71d76e2498be12fd4636631fed448469ce5 100644 (file)
@@ -30,19 +30,23 @@ static ADS_STATUS ads_sasl_ntlmssp_wrap(ADS_STRUCT *ads, uint8 *buf, uint32 len)
        ADS_STATUS status;
        NTSTATUS nt_status;
        DATA_BLOB sig;
+       TALLOC_CTX *frame;
        uint8 *dptr = ads->ldap.out.buf + (4 + NTLMSSP_SIG_SIZE);
 
+       frame = talloc_stackframe();
        /* copy the data to the right location */
        memcpy(dptr, buf, len);
 
        /* create the signature and may encrypt the data */
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
                nt_status = ntlmssp_seal_packet(ntlmssp_state,
+                                               frame,
                                                dptr, len,
                                                dptr, len,
                                                &sig);
        } else {
                nt_status = ntlmssp_sign_packet(ntlmssp_state,
+                                               frame,
                                                dptr, len,
                                                dptr, len,
                                                &sig);
@@ -54,7 +58,7 @@ static ADS_STATUS ads_sasl_ntlmssp_wrap(ADS_STRUCT *ads, uint8 *buf, uint32 len)
        memcpy(ads->ldap.out.buf + 4,
               sig.data, NTLMSSP_SIG_SIZE);
 
-       data_blob_free(&sig);
+       TALLOC_FREE(frame);
 
        /* set how many bytes must be written to the underlying socket */
        ads->ldap.out.left = 4 + NTLMSSP_SIG_SIZE + len;
index 20730928cca112abd0247a5a59188f2a729e5ff0..8ae244b70b7d85014bea945db50bdd2c1c835cf9 100644 (file)
@@ -81,6 +81,7 @@ union ntlmssp_crypt_state {
 };
 
 static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_state,
+                                             TALLOC_CTX *sig_mem_ctx,
                                              const uint8_t *data, size_t length,
                                              const uint8_t *whole_pdu, size_t pdu_length,
                                              enum ntlmssp_direction direction,
@@ -91,7 +92,7 @@ static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_stat
                uint8_t digest[16];
                uint8_t seq_num[4];
 
-               *sig = data_blob(NULL, NTLMSSP_SIG_SIZE);
+               *sig = data_blob_talloc(sig_mem_ctx, NULL, NTLMSSP_SIG_SIZE);
                if (!sig->data) {
                        return NT_STATUS_NO_MEMORY;
                }
@@ -151,7 +152,7 @@ static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_stat
 
                crc = crc32_calc_buffer(data, length);
 
-               ok = msrpc_gen(ntlmssp_state,
+               ok = msrpc_gen(sig_mem_ctx,
                               sig, "dddd",
                               NTLMSSP_SIGN_VERSION, 0, crc,
                               ntlmssp_state->crypt->ntlm.seq_num);
@@ -170,6 +171,7 @@ static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_stat
 }
 
 NTSTATUS ntlmssp_sign_packet(struct ntlmssp_state *ntlmssp_state,
+                            TALLOC_CTX *sig_mem_ctx,
                             const uint8_t *data, size_t length,
                             const uint8_t *whole_pdu, size_t pdu_length,
                             DATA_BLOB *sig)
@@ -187,6 +189,7 @@ NTSTATUS ntlmssp_sign_packet(struct ntlmssp_state *ntlmssp_state,
        }
 
        nt_status = ntlmssp_make_packet_signature(ntlmssp_state,
+                                                 sig_mem_ctx,
                                                  data, length,
                                                  whole_pdu, pdu_length,
                                                  NTLMSSP_SEND, sig, true);
@@ -207,6 +210,7 @@ NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
 {
        DATA_BLOB local_sig;
        NTSTATUS nt_status;
+       TALLOC_CTX *tmp_ctx;
 
        if (!ntlmssp_state->session_key.length) {
                DEBUG(3, ("NO session key, cannot check packet signature\n"));
@@ -218,7 +222,13 @@ NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
                          (unsigned long)sig->length));
        }
 
+       tmp_ctx = talloc_new(ntlmssp_state);
+       if (!tmp_ctx) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
        nt_status = ntlmssp_make_packet_signature(ntlmssp_state,
+                                                 tmp_ctx,
                                                  data, length,
                                                  whole_pdu, pdu_length,
                                                  NTLMSSP_RECEIVE,
@@ -227,7 +237,7 @@ NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0,("NTLMSSP packet sig creation failed with %s\n",
                         nt_errstr(nt_status)));
-               data_blob_free(&local_sig);
+               talloc_free(tmp_ctx);
                return nt_status;
        }
 
@@ -241,7 +251,7 @@ NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
                        dump_data(5, sig->data, sig->length);
 
                        DEBUG(0, ("NTLMSSP NTLM2 packet check failed due to invalid signature!\n"));
-                       data_blob_free(&local_sig);
+                       talloc_free(tmp_ctx);
                        return NT_STATUS_ACCESS_DENIED;
                }
        } else {
@@ -254,14 +264,14 @@ NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
                        dump_data(5, sig->data, sig->length);
 
                        DEBUG(0, ("NTLMSSP NTLM1 packet check failed due to invalid signature!\n"));
-                       data_blob_free(&local_sig);
+                       talloc_free(tmp_ctx);
                        return NT_STATUS_ACCESS_DENIED;
                }
        }
        dump_data_pw("checked ntlmssp signature\n", sig->data, sig->length);
        DEBUG(10,("ntlmssp_check_packet: NTLMSSP signature OK !\n"));
 
-       data_blob_free(&local_sig);
+       talloc_free(tmp_ctx);
        return NT_STATUS_OK;
 }
 
@@ -271,6 +281,7 @@ NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
  */
 
 NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state,
+                            TALLOC_CTX *sig_mem_ctx,
                             uint8_t *data, size_t length,
                             const uint8_t *whole_pdu, size_t pdu_length,
                             DATA_BLOB *sig)
@@ -297,6 +308,7 @@ NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state,
                 * updated with each iteration
                 */
                nt_status = ntlmssp_make_packet_signature(ntlmssp_state,
+                                                         sig_mem_ctx,
                                                          data, length,
                                                          whole_pdu, pdu_length,
                                                          NTLMSSP_SEND,
@@ -317,7 +329,7 @@ NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state,
 
                crc = crc32_calc_buffer(data, length);
 
-               ok = msrpc_gen(ntlmssp_state,
+               ok = msrpc_gen(sig_mem_ctx,
                               sig, "dddd",
                               NTLMSSP_SIGN_VERSION, 0, crc,
                               ntlmssp_state->crypt->ntlm.seq_num);
@@ -362,6 +374,7 @@ NTSTATUS ntlmssp_unseal_packet(struct ntlmssp_state *ntlmssp_state,
                               const uint8_t *whole_pdu, size_t pdu_length,
                               const DATA_BLOB *sig)
 {
+       NTSTATUS status;
        if (!ntlmssp_state->session_key.length) {
                DEBUG(3, ("NO session key, cannot unseal packet\n"));
                return NT_STATUS_NO_USER_SESSION_KEY;
@@ -380,7 +393,16 @@ NTSTATUS ntlmssp_unseal_packet(struct ntlmssp_state *ntlmssp_state,
                                   data, length);
                dump_data_pw("ntlmv1 clear data\n", data, length);
        }
-       return ntlmssp_check_packet(ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
+       status = ntlmssp_check_packet(ntlmssp_state,
+                                     data, length,
+                                     whole_pdu, pdu_length,
+                                     sig);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(1,("NTLMSSP packet check for unseal failed due to invalid signature on %llu bytes of input:\n",
+                        (unsigned long long)length));
+       }
+       return status;
 }
 
 /**
index cff237bc8b0c474b8bc43b345b65e5e8172489db..92d7fef651e2aa89decb10b30e63a3d3c844f6b6 100644 (file)
@@ -117,13 +117,14 @@ NTSTATUS common_ntlm_encrypt_buffer(struct ntlmssp_state *ntlmssp_state,
        char *buf_out;
        size_t data_len = smb_len(buf) - 4; /* Ignore the 0xFF SMB bytes. */
        DATA_BLOB sig;
-
+       TALLOC_CTX *frame;
        *ppbuf_out = NULL;
 
        if (data_len == 0) {
                return NT_STATUS_BUFFER_TOO_SMALL;
        }
 
+       frame = talloc_stackframe();
        /* 
         * We know smb_len can't return a value > 128k, so no int overflow
         * check needed.
@@ -140,6 +141,7 @@ NTSTATUS common_ntlm_encrypt_buffer(struct ntlmssp_state *ntlmssp_state,
        ZERO_STRUCT(sig);
 
        status = ntlmssp_seal_packet(ntlmssp_state,
+                                    frame,
                (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
                data_len,
                (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE,
@@ -147,14 +149,14 @@ NTSTATUS common_ntlm_encrypt_buffer(struct ntlmssp_state *ntlmssp_state,
                &sig);
 
        if (!NT_STATUS_IS_OK(status)) {
-               data_blob_free(&sig);
+               talloc_free(frame);
                SAFE_FREE(buf_out);
                return status;
        }
 
        /* First 16 data bytes are signature for SSPI compatibility. */
        memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
-       data_blob_free(&sig);
+       talloc_free(frame);
        *ppbuf_out = buf_out;
        return NT_STATUS_OK;
 }
index 0cd4d60b5d1365a6c77b7b6eb4733d6f8dc7431b..e248133de34d35f7f2c79b0f70d6ab358ff7e312 100644 (file)
@@ -1976,11 +1976,14 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
        NTSTATUS status;
        DATA_BLOB auth_blob = data_blob_null;
        uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
+       TALLOC_CTX *frame;
 
        if (!cli->auth->a_u.ntlmssp_state) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
+       frame = talloc_stackframe();
+
        /* Init and marshall the auth header. */
        init_rpc_hdr_auth(&auth_info,
                        map_pipe_auth_type_to_rpc_auth_type(
@@ -1991,7 +1994,7 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
 
        if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
                DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
-               data_blob_free(&auth_blob);
+               talloc_free(frame);
                return NT_STATUS_NO_MEMORY;
        }
 
@@ -1999,13 +2002,14 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
                case DCERPC_AUTH_LEVEL_PRIVACY:
                        /* Data portion is encrypted. */
                        status = ntlmssp_seal_packet(cli->auth->a_u.ntlmssp_state,
+                                                    frame,
                                        (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
                                        data_and_pad_len,
                                        (unsigned char *)prs_data_p(outgoing_pdu),
                                        (size_t)prs_offset(outgoing_pdu),
                                        &auth_blob);
                        if (!NT_STATUS_IS_OK(status)) {
-                               data_blob_free(&auth_blob);
+                               talloc_free(frame);
                                return status;
                        }
                        break;
@@ -2013,13 +2017,14 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
                case DCERPC_AUTH_LEVEL_INTEGRITY:
                        /* Data is signed. */
                        status = ntlmssp_sign_packet(cli->auth->a_u.ntlmssp_state,
+                                                    frame,
                                        (unsigned char *)prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
                                        data_and_pad_len,
                                        (unsigned char *)prs_data_p(outgoing_pdu),
                                        (size_t)prs_offset(outgoing_pdu),
                                        &auth_blob);
                        if (!NT_STATUS_IS_OK(status)) {
-                               data_blob_free(&auth_blob);
+                               talloc_free(frame);
                                return status;
                        }
                        break;
@@ -2036,11 +2041,11 @@ static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
        if (!prs_copy_data_in(outgoing_pdu, (const char *)auth_blob.data, NTLMSSP_SIG_SIZE)) {
                DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
                        (unsigned int)NTLMSSP_SIG_SIZE));
-               data_blob_free(&auth_blob);
+               talloc_free(frame);
                return NT_STATUS_NO_MEMORY;
        }
 
-       data_blob_free(&auth_blob);
+       talloc_free(frame);
        return NT_STATUS_OK;
 }
 
index ce087a4e034e52c30c0d23128a22b870e5e046b3..50914acfbde1f2122814e229645629ba8543c50c 100644 (file)
@@ -68,6 +68,7 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p)
        RPC_HDR_AUTH auth_info;
        uint8 auth_type, auth_level;
        struct auth_ntlmssp_state *a = p->auth.a_u.auth_ntlmssp_state;
+       TALLOC_CTX *frame;
 
        /*
         * If we're in the fault state, keep returning fault PDU's until
@@ -222,11 +223,12 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p)
 
        /* Generate the sign blob. */
 
+       frame = talloc_stackframe();
        switch (p->auth.auth_level) {
                case DCERPC_AUTH_LEVEL_PRIVACY:
                        /* Data portion is encrypted. */
                        status = auth_ntlmssp_seal_packet(
-                               a,
+                               a, frame,
                                (uint8_t *)prs_data_p(&p->out_data.frag)
                                + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
                                data_len + ss_padding_len,
@@ -234,7 +236,7 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p)
                                (size_t)prs_offset(&p->out_data.frag),
                                &auth_blob);
                        if (!NT_STATUS_IS_OK(status)) {
-                               data_blob_free(&auth_blob);
+                               talloc_free(frame);
                                prs_mem_free(&p->out_data.frag);
                                return False;
                        }
@@ -242,7 +244,7 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p)
                case DCERPC_AUTH_LEVEL_INTEGRITY:
                        /* Data is signed. */
                        status = auth_ntlmssp_sign_packet(
-                               a,
+                               a, frame,
                                (unsigned char *)prs_data_p(&p->out_data.frag)
                                + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
                                data_len + ss_padding_len,
@@ -250,12 +252,13 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p)
                                (size_t)prs_offset(&p->out_data.frag),
                                &auth_blob);
                        if (!NT_STATUS_IS_OK(status)) {
-                               data_blob_free(&auth_blob);
+                               talloc_free(frame);
                                prs_mem_free(&p->out_data.frag);
                                return False;
                        }
                        break;
                default:
+                       talloc_free(frame);
                        prs_mem_free(&p->out_data.frag);
                        return False;
        }
@@ -265,12 +268,11 @@ static bool create_next_pdu_ntlmssp(pipes_struct *p)
                              NTLMSSP_SIG_SIZE)) {
                DEBUG(0,("create_next_pdu_ntlmssp: failed to add %u bytes auth blob.\n",
                                (unsigned int)NTLMSSP_SIG_SIZE));
-               data_blob_free(&auth_blob);
+               talloc_free(frame);
                prs_mem_free(&p->out_data.frag);
                return False;
        }
-
-       data_blob_free(&auth_blob);
+       talloc_free(frame);
 
        /*
         * Setup the counts for this PDU.