From 321b0a3a63b40f779c71d476fdc5a840d2ced665 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 28 Jul 2006 21:23:53 +0000 Subject: r17292: Try and fix bug #3967 - signing problems on trans calls introduced by signing code simplification. Please test if you've seen signing problems with 3.0.23a. Jeremy. (This used to be commit f462daf02c12cfba634f92e681eb23a09e7d0acf) --- source3/libsmb/clitrans.c | 101 ++++++++++++++++++++++++++----------------- source3/libsmb/smb_signing.c | 69 +++++++++++++++++++++++++++-- 2 files changed, 127 insertions(+), 43 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index 082da67bb8..4f9f21b848 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -95,9 +95,14 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, return False; } + /* Note we're in a trans state. Save the sequence + * numbers for replies. */ + client_set_trans_sign_state_on(cli, mid); + if (this_ldata < ldata || this_lparam < lparam) { /* receive interim response */ if (!cli_receive_smb(cli) || cli_is_error(cli)) { + client_set_trans_sign_state_off(cli, mid); return(False); } @@ -139,6 +144,7 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, show_msg(cli->outbuf); if (!cli_send_smb(cli)) { + client_set_trans_sign_state_off(cli, mid); return False; } @@ -150,9 +156,6 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, } } - /* Note we're in a trans state. Save the sequence - * numbers for replies. */ - return(True); } @@ -168,6 +171,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, unsigned int total_param=0; unsigned int this_data,this_param; NTSTATUS status; + BOOL ret = False; *data_len = *param_len = 0; @@ -182,7 +186,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, DEBUG(0,("Expected %s response, got command 0x%02x\n", trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(cli->inbuf,smb_com))); - return(False); + return False; } /* @@ -194,7 +198,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, status = cli_nt_error(cli); if (NT_STATUS_IS_ERR(status) || NT_STATUS_EQUAL(status,STATUS_NO_MORE_FILES)) { - return False; + goto out; } /* parse out the lengths */ @@ -206,7 +210,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, *data = SMB_REALLOC(*data,total_data); if (!(*data)) { DEBUG(0,("cli_receive_trans: failed to enlarge data buffer\n")); - return False; + goto out; } } @@ -214,7 +218,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, *param = SMB_REALLOC(*param,total_param); if (!(*param)) { DEBUG(0,("cli_receive_trans: failed to enlarge param buffer\n")); - return False; + goto out; } } @@ -225,7 +229,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, if (this_data + *data_len > total_data || this_param + *param_len > total_param) { DEBUG(1,("Data overflow in cli_receive_trans\n")); - return False; + goto out; } if (this_data + *data_len < this_data || @@ -233,7 +237,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, this_param + *param_len < this_param || this_param + *param_len < *param_len) { DEBUG(1,("Data overflow in cli_receive_trans\n")); - return False; + goto out; } if (this_data) { @@ -245,14 +249,14 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, data_offset_out + this_data < data_offset_out || data_offset_out + this_data < this_data) { DEBUG(1,("Data overflow in cli_receive_trans\n")); - return False; + goto out; } if (data_offset_in > cli->bufsize || data_offset_in + this_data > cli->bufsize || data_offset_in + this_data < data_offset_in || data_offset_in + this_data < this_data) { DEBUG(1,("Data overflow in cli_receive_trans\n")); - return False; + goto out; } memcpy(*data + data_offset_out, smb_base(cli->inbuf) + data_offset_in, this_data); @@ -266,14 +270,14 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, param_offset_out + this_param < param_offset_out || param_offset_out + this_param < this_param) { DEBUG(1,("Param overflow in cli_receive_trans\n")); - return False; + goto out; } if (param_offset_in > cli->bufsize || param_offset_in + this_param > cli->bufsize || param_offset_in + this_param < param_offset_in || param_offset_in + this_param < this_param) { DEBUG(1,("Param overflow in cli_receive_trans\n")); - return False; + goto out; } memcpy(*param + param_offset_out, smb_base(cli->inbuf) + param_offset_in, this_param); @@ -281,11 +285,13 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, *data_len += this_data; *param_len += this_param; - if (total_data <= *data_len && total_param <= *param_len) + if (total_data <= *data_len && total_param <= *param_len) { + ret = True; break; + } if (!cli_receive_smb(cli)) { - return False; + goto out; } show_msg(cli->inbuf); @@ -295,10 +301,10 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, DEBUG(0,("Expected %s response, got command 0x%02x\n", trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(cli->inbuf,smb_com))); - return(False); + goto out; } if (NT_STATUS_IS_ERR(cli_nt_error(cli))) { - return(False); + goto out; } /* parse out the total lengths again - they can shrink! */ @@ -307,12 +313,16 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, if (SVAL(cli->inbuf,smb_tprcnt) < total_param) total_param = SVAL(cli->inbuf,smb_tprcnt); - if (total_data <= *data_len && total_param <= *param_len) + if (total_data <= *data_len && total_param <= *param_len) { + ret = True; break; - + } } - return(True); + out: + + client_set_trans_sign_state_off(cli, SVAL(cli->inbuf,smb_mid)); + return ret; } /**************************************************************************** @@ -379,9 +389,14 @@ BOOL cli_send_nt_trans(struct cli_state *cli, return False; } + /* Note we're in a trans state. Save the sequence + * numbers for replies. */ + client_set_trans_sign_state_on(cli, mid); + if (this_ldata < ldata || this_lparam < lparam) { /* receive interim response */ if (!cli_receive_smb(cli) || cli_is_error(cli)) { + client_set_trans_sign_state_off(cli, mid); return(False); } @@ -423,6 +438,7 @@ BOOL cli_send_nt_trans(struct cli_state *cli, show_msg(cli->outbuf); if (!cli_send_smb(cli)) { + client_set_trans_sign_state_off(cli, mid); return False; } @@ -434,9 +450,6 @@ BOOL cli_send_nt_trans(struct cli_state *cli, } } - /* Note we're in a trans state. Save the sequence - * numbers for replies. */ - return(True); } @@ -453,6 +466,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, unsigned int this_data,this_param; uint8 eclass; uint32 ecode; + BOOL ret = False; *data_len = *param_len = 0; @@ -477,7 +491,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, if (cli_is_dos_error(cli)) { cli_dos_error(cli, &eclass, &ecode); if (!(eclass == ERRDOS && ecode == ERRmoredata)) { - return(False); + goto out; } } @@ -487,7 +501,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, if (cli_is_nt_error(cli)) { if (!NT_STATUS_EQUAL(cli_nt_error(cli), NT_STATUS_BUFFER_TOO_SMALL)) { - return(False); + goto out; } } @@ -500,7 +514,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, *data = SMB_REALLOC(*data,total_data); if (!(*data)) { DEBUG(0,("cli_receive_nt_trans: failed to enlarge data buffer to %d\n",total_data)); - return False; + goto out; } } @@ -508,7 +522,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, *param = SMB_REALLOC(*param,total_param); if (!(*param)) { DEBUG(0,("cli_receive_nt_trans: failed to enlarge param buffer to %d\n", total_param)); - return False; + goto out; } } @@ -519,7 +533,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, if (this_data + *data_len > total_data || this_param + *param_len > total_param) { DEBUG(1,("Data overflow in cli_receive_nt_trans\n")); - return False; + goto out; } if (this_data + *data_len < this_data || @@ -527,7 +541,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, this_param + *param_len < this_param || this_param + *param_len < *param_len) { DEBUG(1,("Data overflow in cli_receive_nt_trans\n")); - return False; + goto out; } if (this_data) { @@ -539,14 +553,14 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, data_offset_out + this_data < data_offset_out || data_offset_out + this_data < this_data) { DEBUG(1,("Data overflow in cli_receive_nt_trans\n")); - return False; + goto out; } if (data_offset_in > cli->bufsize || data_offset_in + this_data > cli->bufsize || data_offset_in + this_data < data_offset_in || data_offset_in + this_data < this_data) { DEBUG(1,("Data overflow in cli_receive_nt_trans\n")); - return False; + goto out; } memcpy(*data + data_offset_out, smb_base(cli->inbuf) + data_offset_in, this_data); @@ -561,14 +575,14 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, param_offset_out + this_param < param_offset_out || param_offset_out + this_param < this_param) { DEBUG(1,("Param overflow in cli_receive_nt_trans\n")); - return False; + goto out; } if (param_offset_in > cli->bufsize || param_offset_in + this_param > cli->bufsize || param_offset_in + this_param < param_offset_in || param_offset_in + this_param < this_param) { DEBUG(1,("Param overflow in cli_receive_nt_trans\n")); - return False; + goto out; } memcpy(*param + param_offset_out, smb_base(cli->inbuf) + param_offset_in, this_param); @@ -577,11 +591,13 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, *data_len += this_data; *param_len += this_param; - if (total_data <= *data_len && total_param <= *param_len) + if (total_data <= *data_len && total_param <= *param_len) { + ret = True; break; + } if (!cli_receive_smb(cli)) { - return False; + goto out; } show_msg(cli->inbuf); @@ -590,12 +606,12 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, if (CVAL(cli->inbuf,smb_com) != SMBnttrans) { DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n", CVAL(cli->inbuf,smb_com))); - return(False); + goto out; } if (cli_is_dos_error(cli)) { cli_dos_error(cli, &eclass, &ecode); if(!(eclass == ERRDOS && ecode == ERRmoredata)) { - return(False); + goto out; } } /* @@ -604,7 +620,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, if (cli_is_nt_error(cli)) { if (!NT_STATUS_EQUAL(cli_nt_error(cli), NT_STATUS_BUFFER_TOO_SMALL)) { - return(False); + goto out; } } @@ -614,9 +630,14 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, if (SVAL(cli->inbuf,smb_ntr_TotalParameterCount) < total_param) total_param = SVAL(cli->inbuf,smb_ntr_TotalParameterCount); - if (total_data <= *data_len && total_param <= *param_len) + if (total_data <= *data_len && total_param <= *param_len) { + ret = True; break; + } } - return(True); + out: + + client_set_trans_sign_state_off(cli, SVAL(cli->inbuf,smb_mid)); + return ret; } diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c index 68c259ba03..fd5d8bf06f 100644 --- a/source3/libsmb/smb_signing.c +++ b/source3/libsmb/smb_signing.c @@ -23,9 +23,10 @@ /* Lookup a packet's MID (multiplex id) and figure out it's sequence number */ struct outstanding_packet_lookup { + struct outstanding_packet_lookup *prev, *next; uint16 mid; uint32 reply_seq_num; - struct outstanding_packet_lookup *prev, *next; + BOOL can_delete; /* Set to False in trans state. */ }; struct smb_basic_signing_context { @@ -51,6 +52,7 @@ static BOOL store_sequence_for_reply(struct outstanding_packet_lookup **list, t->mid = mid; t->reply_seq_num = reply_seq_num; + t->can_delete = True; /* * Add to the *start* of the list not the end of the list. @@ -77,8 +79,23 @@ static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list, *reply_seq_num = t->reply_seq_num; DEBUG(10,("get_sequence_for_reply: found seq = %u mid = %u\n", (unsigned int)t->reply_seq_num, (unsigned int)t->mid )); - DLIST_REMOVE(*list, t); - SAFE_FREE(t); + if (t->can_delete) { + DLIST_REMOVE(*list, t); + SAFE_FREE(t); + } + return True; + } + } + return False; +} + +static BOOL set_sequence_can_delete_flag(struct outstanding_packet_lookup **list, uint16 mid, BOOL can_delete_entry) +{ + struct outstanding_packet_lookup *t; + + for (t = *list; t; t = t->next) { + if (t->mid == mid) { + t->can_delete = can_delete_entry; return True; } } @@ -579,6 +596,52 @@ BOOL cli_check_sign_mac(struct cli_state *cli) return True; } +/*********************************************************** + Enter trans/trans2/nttrans state. +************************************************************/ + +BOOL client_set_trans_sign_state_on(struct cli_state *cli, uint16 mid) +{ + struct smb_sign_info *si = &cli->sign_info; + struct smb_basic_signing_context *data = (struct smb_basic_signing_context *)si->signing_context; + + if (!si->doing_signing) { + return True; + } + + if (!set_sequence_can_delete_flag(&data->outstanding_packet_list, mid, False)) { + return False; + } + + return True; +} + +/*********************************************************** + Leave trans/trans2/nttrans state. +************************************************************/ + +BOOL client_set_trans_sign_state_off(struct cli_state *cli, uint16 mid) +{ + uint32 reply_seq_num; + struct smb_sign_info *si = &cli->sign_info; + struct smb_basic_signing_context *data = (struct smb_basic_signing_context *)si->signing_context; + + if (!si->doing_signing) { + return True; + } + + if (!set_sequence_can_delete_flag(&data->outstanding_packet_list, mid, True)) { + return False; + } + + /* Now delete the stored mid entry. */ + if (!get_sequence_for_reply(&data->outstanding_packet_list, mid, &reply_seq_num)) { + return False; + } + + return True; +} + /*********************************************************** SMB signing - Server implementation - send the MAC. ************************************************************/ -- cgit