summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2003-07-24 19:05:32 +0000
committerJeremy Allison <jra@samba.org>2003-07-24 19:05:32 +0000
commitceb68ee051e97afb1cb08e6f458e23e8f475504e (patch)
tree78124e5359f380fabef4cb337cc3d7f750513bc0
parent27db257734c35602fc34985a42335136166f20be (diff)
downloadsamba-ceb68ee051e97afb1cb08e6f458e23e8f475504e.tar.gz
samba-ceb68ee051e97afb1cb08e6f458e23e8f475504e.tar.bz2
samba-ceb68ee051e97afb1cb08e6f458e23e8f475504e.zip
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)
-rw-r--r--source3/include/smb.h4
-rw-r--r--source3/libsmb/smb_signing.c72
-rw-r--r--source3/smbd/process.c9
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)