From d6fa371b92681a327a86239721fc5990d91ad74f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 25 May 2010 20:55:40 +1000 Subject: s3:ntlmssp Use a TALLOC_CTX for ntlmssp_sign_packet() and ntlmssp_seal_packet() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures the results can't be easily left to leak. Andrew Bartlett Signed-off-by: Stefan Metzmacher Signed-off-by: Günther Deschner --- source3/auth/auth_ntlmssp.c | 6 ++++-- source3/include/proto.h | 4 ++++ source3/libads/sasl.c | 6 +++++- source3/libsmb/ntlmssp_sign.c | 38 ++++++++++++++++++++++++++++++-------- source3/libsmb/smb_seal.c | 8 +++++--- source3/rpc_client/cli_pipe.c | 15 ++++++++++----- source3/rpc_server/srv_pipe.c | 16 +++++++++------- 7 files changed, 67 insertions(+), 26 deletions(-) diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c index b455bc505f..e0e0003f9d 100644 --- a/source3/auth/auth_ntlmssp.c +++ b/source3/auth/auth_ntlmssp.c @@ -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, diff --git a/source3/include/proto.h b/source3/include/proto.h index d479edbc9f..472e1793ca 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -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); diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c index 8f7f6c11df..04b9a71d76 100644 --- a/source3/libads/sasl.c +++ b/source3/libads/sasl.c @@ -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; diff --git a/source3/libsmb/ntlmssp_sign.c b/source3/libsmb/ntlmssp_sign.c index 20730928cc..8ae244b70b 100644 --- a/source3/libsmb/ntlmssp_sign.c +++ b/source3/libsmb/ntlmssp_sign.c @@ -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; } /** diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c index cff237bc8b..92d7fef651 100644 --- a/source3/libsmb/smb_seal.c +++ b/source3/libsmb/smb_seal.c @@ -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' */ 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; } diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 0cd4d60b5d..e248133de3 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -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; } diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index ce087a4e03..50914acfbd 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -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. -- cgit