From c0a714ce4b376e6cc643fc0f0a8c4f7439edd62e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 5 Sep 2011 12:14:06 +0200 Subject: [PATCH 1/7] s3:smb2_server: max_trans, max_read and max_write are limited to 64 kilobytes Only if SMB2_CAP_LARGE_MTU is supported we should announce larger limits. metze (cherry picked from commit e603929b9801ad6cc47dead19d27b42fe46489c7) --- source3/smbd/smb2_negprot.c | 20 +++++++++++++++++--- 1 files changed, 17 insertions(+), 3 deletions(-) diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index 9245d6d..414f590 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -76,6 +76,10 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) uint16_t dialect_count; uint16_t dialect = 0; uint32_t capabilities; + uint32_t max_limit; + uint32_t max_trans = lp_smb2_max_trans(); + uint32_t max_read = lp_smb2_max_read(); + uint32_t max_write = lp_smb2_max_write(); /* TODO: drop the connection with INVALID_PARAMETER */ @@ -133,6 +137,16 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) capabilities |= SMB2_CAP_DFS; } + /* + * Unless we implement SMB2_CAP_LARGE_MTU, + * 0x10000 (65536) is the maximum allowed message size + */ + max_limit = 0x10000; + + max_trans = MIN(max_limit, max_trans); + max_read = MIN(max_limit, max_read); + max_write = MIN(max_limit, max_write); + security_offset = SMB2_HDR_BODY + 0x40; #if 1 @@ -158,9 +172,9 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) negprot_spnego_blob.data, 16); /* server guid */ SIVAL(outbody.data, 0x18, capabilities); /* capabilities */ - SIVAL(outbody.data, 0x1C, lp_smb2_max_trans()); /* max transact size */ - SIVAL(outbody.data, 0x20, lp_smb2_max_read()); /* max read size */ - SIVAL(outbody.data, 0x24, lp_smb2_max_write()); /* max write size */ + SIVAL(outbody.data, 0x1C, max_trans); /* max transact size */ + SIVAL(outbody.data, 0x20, max_trans); /* max read size */ + SIVAL(outbody.data, 0x24, max_trans); /* max write size */ SBVAL(outbody.data, 0x28, 0); /* system time */ SBVAL(outbody.data, 0x30, 0); /* server start time */ SSVAL(outbody.data, 0x38, -- 1.7.4.1 From 2e0f957c4aae669c5b875f89e8592b3ec5fda74d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 Sep 2011 06:37:35 +0200 Subject: [PATCH 2/7] s3:smbd: disconnect the socket if we got an unexpected request If we got a SMB2_OP_NEGPROT after the protocol is already negotiated or if we got a non SMB2_OP_NEGPROT before the protocol was negotiated we should close the connection (as windows does). metze Autobuild-User: Stefan Metzmacher Autobuild-Date: Fri Sep 23 12:30:50 CEST 2011 on sn-devel-104 (cherry picked from commit 5494856294384df4360d85e68abc03c43dc16e06) --- source3/smbd/smb2_negprot.c | 1 - source3/smbd/smb2_server.c | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletions(-) diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index 414f590..a9d432a 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -81,7 +81,6 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) uint32_t max_read = lp_smb2_max_read(); uint32_t max_write = lp_smb2_max_write(); -/* TODO: drop the connection with INVALID_PARAMETER */ status = smbd_smb2_request_verify_sizes(req, 0x24); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 0d22d84..1c50d21 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -1203,6 +1203,26 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req) smb2_opcode_name(opcode), (unsigned long long)mid)); + if (get_Protocol() >= PROTOCOL_SMB2) { + /* + * once the protocol is negotiated + * SMB2_OP_NEGPROT is not allowed anymore + */ + if (opcode == SMB2_OP_NEGPROT) { + /* drop the connection */ + return NT_STATUS_INVALID_PARAMETER; + } + } else { + /* + * if the protocol is not negotiated yet + * only SMB2_OP_NEGPROT is allowed. + */ + if (opcode != SMB2_OP_NEGPROT) { + /* drop the connection */ + return NT_STATUS_INVALID_PARAMETER; + } + } + allowed_flags = SMB2_HDR_FLAG_CHAINED | SMB2_HDR_FLAG_SIGNED | SMB2_HDR_FLAG_DFS; -- 1.7.4.1 From 4195a44312dc9d48c2d5ee8266866266f35dfbe0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 12 Oct 2011 18:34:26 +0200 Subject: [PATCH 3/7] s4:torture/smb2: we only support 64KB reads/writes for now We don't have multi-credit support yet. metze (cherry picked from commit 77f739f03a32965b676d97a6f082bb3e023014ef) --- source4/torture/smb2/connect.c | 12 ++++++------ source4/torture/smb2/read.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source4/torture/smb2/connect.c b/source4/torture/smb2/connect.c index 1b69c18..b383a67 100644 --- a/source4/torture/smb2/connect.c +++ b/source4/torture/smb2/connect.c @@ -71,14 +71,14 @@ static NTSTATUS torture_smb2_write(struct torture_context *tctx, struct smb2_tre NTSTATUS status; DATA_BLOB data; int i; + uint32_t size = torture_setting_int(tctx, "smb2maxwrite", 64*1024); - if (torture_setting_bool(tctx, "dangerous", false)) { - data = data_blob_talloc(tree, NULL, 160000); - } else if (torture_setting_bool(tctx, "samba4", false)) { - data = data_blob_talloc(tree, NULL, UINT16_MAX); - } else { - data = data_blob_talloc(tree, NULL, torture_setting_int(tctx, "smb2maxwrite", 120000)); + data = data_blob_talloc(tree, NULL, size); + if (size != data.length) { + printf("data_blob_talloc(%s) failed\n", size); + return NT_STATUS_NO_MEMORY; } + for (i=0;i Date: Fri, 23 Sep 2011 17:18:14 +0200 Subject: [PATCH 4/7] s3:smb2_server: remember the max_{trans,read,write} sizes we negotiated (bug #8473) We should enforce the negotiated max sizes instead of the lp_smb2_max_*() sizes. metze (cherry picked from commit 40ea66c5dda91ba3f74bed7db1ce02f6c8b4ffeb) --- source3/smbd/globals.h | 3 +++ source3/smbd/smb2_find.c | 2 +- source3/smbd/smb2_negprot.c | 4 +++- source3/smbd/smb2_notify.c | 2 +- source3/smbd/smb2_read.c | 4 ++-- source3/smbd/smb2_write.c | 5 ++--- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 7033848..9304a43 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -604,6 +604,9 @@ struct smbd_server_connection { uint64_t seqnum_low; uint32_t credits_granted; uint32_t max_credits; + uint32_t max_trans; + uint32_t max_read; + uint32_t max_write; struct bitmap *credits_bitmap; bool compound_related_in_progress; } smb2; diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c index 4a49f2a..3dcc768 100644 --- a/source3/smbd/smb2_find.c +++ b/source3/smbd/smb2_find.c @@ -281,7 +281,7 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - if (in_output_buffer_length > lp_smb2_max_trans()) { + if (in_output_buffer_length > smb2req->sconn->smb2.max_trans) { tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return tevent_req_post(req, ev); } diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index a9d432a..2f45b8c 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -81,7 +81,6 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) uint32_t max_read = lp_smb2_max_read(); uint32_t max_write = lp_smb2_max_write(); - status = smbd_smb2_request_verify_sizes(req, 0x24); if (!NT_STATUS_IS_OK(status)) { return smbd_smb2_request_error(req, status); @@ -185,6 +184,9 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) outdyn = security_buffer; req->sconn->using_smb2 = true; + req->sconn->smb2.max_trans = max_trans; + req->sconn->smb2.max_read = max_read; + req->sconn->smb2.max_write = max_write; return smbd_smb2_request_done(req, outbody, &outdyn); } diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c index a8b1eb4..49c6a54 100644 --- a/source3/smbd/smb2_notify.c +++ b/source3/smbd/smb2_notify.c @@ -73,7 +73,7 @@ NTSTATUS smbd_smb2_request_process_notify(struct smbd_smb2_request *req) * 0x00010000 is what Windows 7 uses, * Windows 2008 uses 0x00080000 */ - if (in_output_buffer_length > lp_smb2_max_trans()) { + if (in_output_buffer_length > req->sconn->smb2.max_trans) { return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c index 89fc420..21082e6 100644 --- a/source3/smbd/smb2_read.c +++ b/source3/smbd/smb2_read.c @@ -74,9 +74,9 @@ NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req) in_remaining_bytes = IVAL(inbody, 0x28); /* check the max read size */ - if (in_length > lp_smb2_max_read()) { + if (in_length > req->sconn->smb2.max_read) { DEBUG(0,("here:%s: 0x%08X: 0x%08X\n", - __location__, in_length, lp_smb2_max_read())); + __location__, in_length, req->sconn->smb2.max_read)); return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c index 0202098..3a6ea9b 100644 --- a/source3/smbd/smb2_write.c +++ b/source3/smbd/smb2_write.c @@ -78,11 +78,10 @@ NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req) } /* check the max write size */ - if (in_data_length > lp_smb2_max_write()) { - /* This is a warning. */ + if (in_data_length > req->sconn->smb2.max_write) { DEBUG(2,("smbd_smb2_request_process_write : " "client ignored max write :%s: 0x%08X: 0x%08X\n", - __location__, in_data_length, lp_smb2_max_write())); + __location__, in_data_length, req->sconn->smb2.max_write)); #if 0 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); #endif -- 1.7.4.1 From e07e5a2806b88f68db44c854021e9686dba1c6f7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 12 Oct 2011 16:58:46 +0200 Subject: [PATCH 5/7] s3:smb2_server: reject writes larger then the negotiated max_write size (bug #8473) metze (cherry picked from commit 6981f1114792cc251bf1e05183dd88f5d351ab09) --- source3/smbd/smb2_write.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c index 3a6ea9b..b2360ca 100644 --- a/source3/smbd/smb2_write.c +++ b/source3/smbd/smb2_write.c @@ -82,9 +82,7 @@ NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req) DEBUG(2,("smbd_smb2_request_process_write : " "client ignored max write :%s: 0x%08X: 0x%08X\n", __location__, in_data_length, req->sconn->smb2.max_write)); -#if 0 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); -#endif } in_data_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base; -- 1.7.4.1 From 3bba169e8ece23340c1f68fc05b8e094378779a5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 12 Oct 2011 17:46:50 +0200 Subject: [PATCH 6/7] s3:smb2_server: get/set info are limited by max_trans size (bug #8473) metze Autobuild-User: Stefan Metzmacher Autobuild-Date: Thu Oct 13 03:32:02 CEST 2011 on sn-devel-104 (cherry picked from commit 5e04231e961f10656384a6f16104d0d55b6f3e0e) --- source3/smbd/smb2_getinfo.c | 7 +++++++ source3/smbd/smb2_setinfo.c | 4 ++++ 2 files changed, 11 insertions(+), 0 deletions(-) diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index 61e0cfa..c5d2d62 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -90,6 +90,13 @@ NTSTATUS smbd_smb2_request_process_getinfo(struct smbd_smb2_request *req) in_input_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base; in_input_buffer.length = in_input_buffer_length; + if (in_input_buffer.length > req->sconn->smb2.max_trans) { + return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); + } + if (in_output_buffer_length > req->sconn->smb2.max_trans) { + return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); + } + if (req->compat_chain_fsp) { /* skip check */ } else if (in_file_id_persistent != in_file_id_volatile) { diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c index 2d39f11..751190a 100644 --- a/source3/smbd/smb2_setinfo.c +++ b/source3/smbd/smb2_setinfo.c @@ -81,6 +81,10 @@ NTSTATUS smbd_smb2_request_process_setinfo(struct smbd_smb2_request *req) in_input_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base; in_input_buffer.length = in_input_buffer_length; + if (in_input_buffer.length > req->sconn->smb2.max_trans) { + return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); + } + if (req->compat_chain_fsp) { /* skip check */ } else if (in_file_id_persistent != in_file_id_volatile) { -- 1.7.4.1 From e731bc3262c30abc76157df7c415f0ee615d2015 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Oct 2011 14:00:32 -0700 Subject: [PATCH 7/7] Another part of the fix for Bug 8473 - smb2_find uses a hard coded max reply size of 0x10000 instead of smb2_max_trans. Change the defaults and the documentation to reflect the 64k limit. Signed-off-by: Stefan Metzmacher Autobuild-User: Stefan Metzmacher Autobuild-Date: Thu Oct 13 12:22:23 CEST 2011 on sn-devel-104 (cherry picked from commit d2a9e8df35be1516f22f0ef78356de6d4b02d4d3) --- docs-xml/smbdotconf/protocol/smb2maxcredits.xml | 2 +- docs-xml/smbdotconf/protocol/smb2maxread.xml | 4 ++-- docs-xml/smbdotconf/protocol/smb2maxtrans.xml | 4 ++-- docs-xml/smbdotconf/protocol/smb2maxwrite.xml | 4 ++-- source3/include/local.h | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs-xml/smbdotconf/protocol/smb2maxcredits.xml b/docs-xml/smbdotconf/protocol/smb2maxcredits.xml index 310b898..3cc219d 100644 --- a/docs-xml/smbdotconf/protocol/smb2maxcredits.xml +++ b/docs-xml/smbdotconf/protocol/smb2maxcredits.xml @@ -11,5 +11,5 @@ parameter for SMB1. You should never need to set this parameter. The default is 8192 credits, which is the same as a Windows 2008R2 SMB2 server. -128 +8192 diff --git a/docs-xml/smbdotconf/protocol/smb2maxread.xml b/docs-xml/smbdotconf/protocol/smb2maxread.xml index f4bcb4b..2666821 100644 --- a/docs-xml/smbdotconf/protocol/smb2maxread.xml +++ b/docs-xml/smbdotconf/protocol/smb2maxread.xml @@ -8,10 +8,10 @@ 8 will return to a client, informing the client of the largest size that may be returned by a single SMB2 read call. -The default is 1048576 bytes (1MB), which is the same as a Windows7 SMB2 server. +The maximum is 65536 bytes (64KB), which is the same as a Windows Vista SMB2 server. smb2 max write smb2 max trans -1048576 +65536 diff --git a/docs-xml/smbdotconf/protocol/smb2maxtrans.xml b/docs-xml/smbdotconf/protocol/smb2maxtrans.xml index dd654f4..1c01ccc 100644 --- a/docs-xml/smbdotconf/protocol/smb2maxtrans.xml +++ b/docs-xml/smbdotconf/protocol/smb2maxtrans.xml @@ -8,10 +8,10 @@ 8 will return to a client, informing the client of the largest size of buffer that may be used in querying file meta-data via QUERY_INFO and related SMB2 calls. -The default is 1048576 bytes (1MB), which is the same as a Windows7 SMB2 server. +The maximum is 65536 bytes (64KB), which is the same as a Windows Vista SMB2 server. smb2 max read smb2 max write -1048576 +65536 diff --git a/docs-xml/smbdotconf/protocol/smb2maxwrite.xml b/docs-xml/smbdotconf/protocol/smb2maxwrite.xml index cdbc47a..a302a94 100644 --- a/docs-xml/smbdotconf/protocol/smb2maxwrite.xml +++ b/docs-xml/smbdotconf/protocol/smb2maxwrite.xml @@ -8,10 +8,10 @@ 8 will return to a client, informing the client of the largest size that may be sent to the server by a single SMB2 write call. -The default is 1048576 bytes (1MB), which is the same as a Windows7 SMB2 server. +The maximum is 65536 bytes (64KB), which is the same as a Windows Vista SMB2 server. smb2 max read smb2 max trans -1048576 +65536 diff --git a/source3/include/local.h b/source3/include/local.h index 807d3c9..d659522 100644 --- a/source3/include/local.h +++ b/source3/include/local.h @@ -261,9 +261,9 @@ #define CLIENT_NDR_PADDING_SIZE 8 #define SERVER_NDR_PADDING_SIZE 8 -#define DEFAULT_SMB2_MAX_READ (1024*1024) -#define DEFAULT_SMB2_MAX_WRITE (1024*1024) -#define DEFAULT_SMB2_MAX_TRANSACT (1024*1024) +#define DEFAULT_SMB2_MAX_READ (64*1024) +#define DEFAULT_SMB2_MAX_WRITE (64*1024) +#define DEFAULT_SMB2_MAX_TRANSACT (64*1024) #define DEFAULT_SMB2_MAX_CREDITS 8192 #define DEFAULT_SMB2_MAX_CREDIT_BITMAP_FACTOR 2 -- 1.7.4.1