From ceb68ee051e97afb1cb08e6f458e23e8f475504e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jul 2003 19:05:32 +0000 Subject: Fix packet signing with asynchronous oplock breaks. Removed bad error message due to w2k bug. I think this code is now working.... Need more testing of course but works on all the obvious cases I can think of. Jeremy. (This used to be commit a6e537f6611cc1357fffea0b69901fba7c9ad6ea) --- source3/include/smb.h | 4 +-- source3/libsmb/smb_signing.c | 72 +++++++++++++++++++++++++++++++++++++++++--- source3/smbd/process.c | 9 ++++-- 3 files changed, 75 insertions(+), 10 deletions(-) diff --git a/source3/include/smb.h b/source3/include/smb.h index 85ee5cdfc6..9800e21dff 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -79,9 +79,7 @@ typedef int BOOL; #define READ_TIMEOUT 1 #define READ_EOF 2 #define READ_ERROR 3 - -/* This error code can go into the client smb_rw_error. */ -#define WRITE_ERROR 4 +#define WRITE_ERROR 4 /* This error code can go into the client smb_rw_error. */ #define READ_BAD_SIG 5 #define DIR_STRUCT_SIZE 43 diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c index 1fe3f99c8a..4a98b84826 100644 --- a/source3/libsmb/smb_signing.c +++ b/source3/libsmb/smb_signing.c @@ -187,7 +187,12 @@ static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good) if (!good) { if (si->doing_signing) { - DEBUG(1, ("SMB signature check failed!\n")); + struct smb_basic_signing_context *data = si->signing_context; + + /* W2K sends a bad first signature but the sign engine is on.... JRA. */ + if (data->send_seq_num > 1) + DEBUG(1, ("SMB signature check failed!\n")); + return False; } else { DEBUG(3, ("Server did not sign reply correctly\n")); @@ -491,6 +496,21 @@ BOOL cli_check_sign_mac(struct cli_state *cli) return True; } +static BOOL outgoing_packet_is_oplock_break(char *outbuf) +{ + if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) { + return False; + } + + if (CVAL(outbuf,smb_com) != SMBlockingX) + return False; + + if (CVAL(outbuf,smb_vwv3) != LOCKING_ANDX_OPLOCK_RELEASE) + return False; + + return True; +} + /*********************************************************** SMB signing - Server implementation - send the MAC. ************************************************************/ @@ -502,12 +522,32 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) uint32 send_seq_number = data->send_seq_num; BOOL was_deferred_packet; - if (!si->doing_signing) + if (!si->doing_signing) { + if (si->allow_smb_signing && si->negotiated_smb_signing) { + uint16 mid = SVAL(outbuf, smb_mid); + + was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, + mid, &send_seq_number); + if (!was_deferred_packet) { + /* + * Is this an outgoing oplock break ? If so, store the + * mid in the outstanding list. + */ + + if (outgoing_packet_is_oplock_break(outbuf)) { + store_sequence_for_reply(&data->outstanding_packet_list, + mid, data->send_seq_num); + } + + data->send_seq_num++; + } + } return; + } /* JRA Paranioa test - we should be able to get rid of this... */ if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) { - DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n", + DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n", smb_len(outbuf) )); abort(); } @@ -555,8 +595,13 @@ static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si) return False; } - reply_seq_number = data->send_seq_num; - data->send_seq_num++; + /* Oplock break requests store an outgoing mid in the packet list. */ + if (!get_sequence_for_reply(&data->outstanding_packet_list, + SVAL(inbuf, smb_mid), + &reply_seq_number)) { + reply_seq_number = data->send_seq_num; + data->send_seq_num++; + } simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac); @@ -564,11 +609,28 @@ static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si) good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0); if (!good) { + DEBUG(5, ("srv_check_incoming_message: BAD SIG: wanted SMB signature of\n")); dump_data(5, calc_md5_mac, 8); DEBUG(5, ("srv_check_incoming_message: BAD SIG: got SMB signature of\n")); dump_data(5, server_sent_mac, 8); + +#if 0 /* JRATEST */ + { + int i; + reply_seq_number -= 5; + for (i = 0; i < 10; i++, reply_seq_number++) { + simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac); + if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) { + DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches.\n", + reply_seq_number )); + break; + } + } + } +#endif /* JRATEST */ + } return signing_good(inbuf, si, good); } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index fb85f38119..dce1c4bc03 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1087,16 +1087,21 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t extern int keepalive; if (smb_read_error == READ_EOF) { - DEBUG(3,("end of file from client\n")); + DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n")); return False; } if (smb_read_error == READ_ERROR) { - DEBUG(3,("receive_smb error (%s) exiting\n", + DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n", strerror(errno))); return False; } + if (smb_read_error == READ_BAD_SIG) { + DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n")); + return False; + } + *last_timeout_processing_time = t = time(NULL); if(last_keepalive_sent_time == 0) -- cgit