From 255ffaf717a6cd83d58ff4b978c80dbe8ba96bfa Mon Sep 17 00:00:00 2001 From: Ralph Wuerthner Date: Wed, 10 Jul 2013 08:59:58 +0200 Subject: [PATCH 01/13] s3:smbd: return NT_STATUS_INFO_LENGTH_MISMATCH for GetInfo in case output_buffer_length is too small Reviewed-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit a93f9c3d33e442c84d0c9da7eb5d25ca4b54fc33) --- source3/smbd/smb2_getinfo.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index 5616c84..ec0bad0 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -498,6 +498,11 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } + if (state->out_output_buffer.length > in_output_buffer_length) { + tevent_req_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH); + return tevent_req_post(req, ev); + } + tevent_req_done(req); return tevent_req_post(req, ev); } -- 1.8.4 From 0f78b9085fe98d9ac992f5f3a6222934332b6610 Mon Sep 17 00:00:00 2001 From: Ralph Wuerthner Date: Fri, 5 Jul 2013 11:03:16 +0200 Subject: [PATCH 02/13] s3:smbd: allow GetInfo responses with STATUS_BUFFER_OVERFLOW to return partial, but valid data Reviewed-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit a91d2b05bab329a8a9772c2c79a3b1e02933182e) --- source3/smbd/smb2_getinfo.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index ec0bad0..7a41b19 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -159,7 +159,10 @@ static void smbd_smb2_request_getinfo_done(struct tevent_req *subreq) return; } - if (!NT_STATUS_IS_OK(call_status)) { + /* some GetInfo responses set STATUS_BUFFER_OVERFLOW and return partial, + but valid data */ + if (!(NT_STATUS_IS_OK(call_status) || + NT_STATUS_EQUAL(call_status, STATUS_BUFFER_OVERFLOW))) { /* Return a specific error with data. */ error = smbd_smb2_request_error_ex(req, call_status, @@ -194,7 +197,7 @@ static void smbd_smb2_request_getinfo_done(struct tevent_req *subreq) outdyn = out_output_buffer; - error = smbd_smb2_request_done(req, outbody, &outdyn); + error = smbd_smb2_request_done_ex(req, call_status, outbody, &outdyn, __location__); if (!NT_STATUS_IS_OK(error)) { smbd_server_connection_terminate(req->sconn, nt_errstr(error)); @@ -416,7 +419,10 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, fsp->fsp_name, &data, &data_size); - if (!NT_STATUS_IS_OK(status)) { + /* some responses set STATUS_BUFFER_OVERFLOW and return + partial, but valid data */ + if (!(NT_STATUS_IS_OK(status) || + NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW))) { SAFE_FREE(data); if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) { status = NT_STATUS_INVALID_INFO_CLASS; @@ -503,6 +509,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } + state->status = status; tevent_req_done(req); return tevent_req_post(req, ev); } -- 1.8.4 From 3b9358abb373959748b89ce78bf23b1a2633f2f2 Mon Sep 17 00:00:00 2001 From: Ralph Wuerthner Date: Fri, 5 Jul 2013 11:32:27 +0200 Subject: [PATCH 03/13] s3:smbd: allow status code in smbd_do_qfsinfo() to be set by information class handler Reviewed-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit 616777f029e462f53c5118d79de8c6405a5fb7c1) --- source3/smbd/trans2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 25de505..4dd40ad 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3071,6 +3071,7 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, uint32 additional_flags = 0; struct smb_filename smb_fname; SMB_STRUCT_STAT st; + NTSTATUS status = NT_STATUS_OK; if (fname == NULL || fname->base_name == NULL) { filename = "."; @@ -3602,7 +3603,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned } *ret_data_len = data_len; - return NT_STATUS_OK; + return status; } /**************************************************************************** -- 1.8.4 From a6c5e14c031f29bd82ad8be4553252f121c78335 Mon Sep 17 00:00:00 2001 From: Ralph Wuerthner Date: Wed, 10 Jul 2013 15:52:06 +0200 Subject: [PATCH 04/13] s3:smbd: allow info class SMB_QUERY_FS_VOLUME_INFO to return partial data Reviewed-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit ec46f6b91941e38dd92f8e0fb0f278592e3157b6) --- source3/smbd/trans2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4dd40ad..2d4b15d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3232,6 +3232,12 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", (int)strlen(vname),vname, lp_servicename(talloc_tos(), snum))); + if (max_data_bytes >= 24 && data_len > max_data_bytes) { + /* the client only requested a portion of the + volume label */ + data_len = max_data_bytes; + status = STATUS_BUFFER_OVERFLOW; + } break; case SMB_QUERY_FS_SIZE_INFO: -- 1.8.4 From bb6608981300f35b8c83eb432020f481b8ebf29a Mon Sep 17 00:00:00 2001 From: Ralph Wuerthner Date: Wed, 10 Jul 2013 16:43:39 +0200 Subject: [PATCH 05/13] s3:smbd: allow info class SMB_QUERY_FS_ATTRIBUTE_INFO to return partial data Reviewed-by: Jeremy Allison Reviewed-by: Volker Lendecke (cherry picked from commit 270d29a743a030653037cb176f3764bec3c79b6c) --- source3/smbd/trans2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2d4b15d..63318ac 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3202,6 +3202,12 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u STR_UNICODE); SIVAL(pdata,8,len); data_len = 12 + len; + if (max_data_bytes >= 16 && data_len > max_data_bytes) { + /* the client only requested a portion of the + file system name */ + data_len = max_data_bytes; + status = STATUS_BUFFER_OVERFLOW; + } break; case SMB_QUERY_FS_LABEL_INFO: -- 1.8.4 From f7a5576e702e7b31f4ac0e6273b73cdcf118c710 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 26 Aug 2013 08:36:14 +0000 Subject: [PATCH 06/13] smbd: Use #defines in smb2_getinfo_send Signed-off-by: Volker Lendecke Reviewed-by: David Disseldorp Autobuild-User(master): David Disseldorp Autobuild-Date(master): Tue Aug 27 15:08:08 CEST 2013 on sn-devel-104 (cherry picked from commit 323cccd35d06c7327c19dc5cb891043507624d7d) --- source3/smbd/smb2_getinfo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index 7a41b19..4420f94 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -282,7 +282,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, } switch (in_info_type) { - case 0x01:/* SMB2_GETINFO_FILE */ + case SMB2_GETINFO_FILE: { uint16_t file_info_level; char *data = NULL; @@ -403,7 +403,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, break; } - case 0x02:/* SMB2_GETINFO_FS */ + case SMB2_GETINFO_FS: { uint16_t file_info_level; char *data = NULL; @@ -443,7 +443,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, break; } - case 0x03:/* SMB2_GETINFO_SEC */ + case SMB2_GETINFO_SECURITY: { uint8_t *p_marshalled_sd = NULL; size_t sd_size = 0; @@ -489,7 +489,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, break; } - case 0x04: /* SMB2_0_INFO_QUOTA */ + case SMB2_GETINFO_QUOTA: tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED); return tevent_req_post(req, ev); -- 1.8.4 From 0c7288d4bbbc3582b856f5fa1b9640a294349403 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 27 Aug 2013 09:06:27 +0000 Subject: [PATCH 07/13] smbd: qfilepathinfo has fixed/variable buffers The error message will have to change depending whether the buffer is too small for the fixed or variable buffers Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106 Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 53123996033594f68a3fc9037474aada3aef0750) --- source3/smbd/globals.h | 1 + source3/smbd/smb2_getinfo.c | 2 ++ source3/smbd/trans2.c | 22 ++++++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index d618aea..6ccb57e 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -138,6 +138,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, char *lock_data, uint16_t flags2, unsigned int max_data_bytes, + size_t *fixed_portion, char **ppdata, unsigned int *pdata_size); diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index 4420f94..0d75c36 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -293,6 +293,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, struct ea_list *ea_list = NULL; int lock_data_count = 0; char *lock_data = NULL; + size_t fixed_portion; ZERO_STRUCT(write_time_ts); @@ -380,6 +381,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, lock_data, STR_UNICODE, in_output_buffer_length, + &fixed_portion, &data, &data_size); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 63318ac..2e9f828 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4370,6 +4370,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, char *lock_data, uint16_t flags2, unsigned int max_data_bytes, + size_t *fixed_portion, char **ppdata, unsigned int *pdata_size) { @@ -4506,6 +4507,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, BasicFileInformationTest. -tpot */ file_index = get_FileIndex(conn, psbuf); + *fixed_portion = 0; + switch (info_level) { case SMB_INFO_STANDARD: DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n")); @@ -4652,6 +4655,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, DEBUG(5,("write: %s ", ctime(&mtime))); DEBUG(5,("change: %s ", ctime(&c_time))); DEBUG(5,("mode: %x\n", mode)); + *fixed_portion = data_size; break; case SMB_FILE_STANDARD_INFORMATION: @@ -4665,6 +4669,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, SCVAL(pdata,20,delete_pending?1:0); SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0); SSVAL(pdata,22,0); /* Padding. */ + *fixed_portion = 24; break; case SMB_FILE_EA_INFORMATION: @@ -4674,6 +4679,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, estimate_ea_size(conn, fsp, smb_fname); DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n")); data_size = 4; + *fixed_portion = 4; SIVAL(pdata,0,ea_size); break; } @@ -4695,6 +4701,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, STR_UNICODE); data_size = 4 + len; SIVAL(pdata,0,len); + *fixed_portion = 8; break; } @@ -4758,6 +4765,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, SIVAL(pdata,0,len); pdata += 4 + len; data_size = PTR_DIFF(pdata,(*ppdata)); + *fixed_portion = 10; break; } @@ -4795,6 +4803,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, SIVAL(pdata,0,len); pdata += 4 + len; data_size = PTR_DIFF(pdata,(*ppdata)); + *fixed_portion = 104; break; } case SMB_FILE_INTERNAL_INFORMATION: @@ -4802,12 +4811,14 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n")); SBVAL(pdata, 0, file_index); data_size = 8; + *fixed_portion = 8; break; case SMB_FILE_ACCESS_INFORMATION: DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n")); SIVAL(pdata, 0, access_mask); data_size = 4; + *fixed_portion = 4; break; case SMB_FILE_NAME_INFORMATION: @@ -4825,24 +4836,28 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n")); data_size = 1; SCVAL(pdata,0,delete_pending); + *fixed_portion = 1; break; case SMB_FILE_POSITION_INFORMATION: DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n")); data_size = 8; SOFF_T(pdata,0,pos); + *fixed_portion = 8; break; case SMB_FILE_MODE_INFORMATION: DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n")); SIVAL(pdata,0,mode); data_size = 4; + *fixed_portion = 4; break; case SMB_FILE_ALIGNMENT_INFORMATION: DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n")); SIVAL(pdata,0,0); /* No alignment needed. */ data_size = 4; + *fixed_portion = 4; break; /* @@ -4887,6 +4902,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, TALLOC_FREE(streams); + *fixed_portion = 32; + break; } case SMB_QUERY_COMPRESSION_INFO: @@ -4896,6 +4913,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, SIVAL(pdata,8,0); /* ??? */ SIVAL(pdata,12,0); /* ??? */ data_size = 16; + *fixed_portion = 16; break; case SMB_FILE_NETWORK_OPEN_INFORMATION: @@ -4909,6 +4927,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, SIVAL(pdata,48,mode); SIVAL(pdata,52,0); /* ??? */ data_size = 56; + *fixed_portion = 56; break; case SMB_FILE_ATTRIBUTE_TAG_INFORMATION: @@ -4916,6 +4935,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, SIVAL(pdata,0,mode); SIVAL(pdata,4,0); data_size = 8; + *fixed_portion = 8; break; /* @@ -5189,6 +5209,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, struct ea_list *ea_list = NULL; int lock_data_count = 0; char *lock_data = NULL; + size_t fixed_portion; NTSTATUS status = NT_STATUS_OK; if (!params) { @@ -5548,6 +5569,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd ea_list, lock_data_count, lock_data, req->flags2, max_data_bytes, + &fixed_portion, ppdata, &data_size); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); -- 1.8.4 From 4b1e3947a029c0bb4e4f4454bd44a7e6fd1331af Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 27 Aug 2013 09:06:27 +0000 Subject: [PATCH 08/13] smbd: qfsinfo has fixed/variable buffers The error message will have to change depending whether the buffer is too small for the fixed or variable buffers Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106 Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit ac41df91a5a425633fc716ca02187e753879d795) --- source3/smbd/globals.h | 1 + source3/smbd/smb2_getinfo.c | 2 ++ source3/smbd/trans2.c | 10 ++++++++++ 3 files changed, 13 insertions(+) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 6ccb57e..9ea5e25 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -156,6 +156,7 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, uint16_t info_level, uint16_t flags2, unsigned int max_data_bytes, + size_t *fixed_portion, struct smb_filename *smb_fname, char **ppdata, int *ret_data_len); diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index 0d75c36..698e775 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -410,6 +410,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, uint16_t file_info_level; char *data = NULL; int data_size = 0; + size_t fixed_portion; /* the levels directly map to the passthru levels */ file_info_level = in_file_info_class + 1000; @@ -418,6 +419,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, file_info_level, STR_UNICODE, in_output_buffer_length, + &fixed_portion, fsp->fsp_name, &data, &data_size); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 2e9f828..bb9e98d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3058,6 +3058,7 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, uint16_t info_level, uint16_t flags2, unsigned int max_data_bytes, + size_t *fixed_portion, struct smb_filename *fname, char **ppdata, int *ret_data_len) @@ -3110,6 +3111,8 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn, memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1; + *fixed_portion = 0; + switch (info_level) { case SMB_INFO_ALLOCATION: { @@ -3208,6 +3211,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u data_len = max_data_bytes; status = STATUS_BUFFER_OVERFLOW; } + *fixed_portion = 16; break; case SMB_QUERY_FS_LABEL_INFO: @@ -3244,6 +3248,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u data_len = max_data_bytes; status = STATUS_BUFFER_OVERFLOW; } + *fixed_portion = 24; break; case SMB_QUERY_FS_SIZE_INFO: @@ -3276,6 +3281,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned SBIG_UINT(pdata,8,dfree); SIVAL(pdata,16,sectors_per_unit); SIVAL(pdata,20,bytes_per_sector); + *fixed_portion = 24; break; } @@ -3309,6 +3315,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */ SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */ SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */ + *fixed_portion = 32; break; } @@ -3323,6 +3330,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned data_len = 8; SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */ SIVAL(pdata,4,characteristics); + *fixed_portion = 8; break; } @@ -3631,6 +3639,7 @@ static void call_trans2qfsinfo(connection_struct *conn, char *params = *pparams; uint16_t info_level; int data_len = 0; + size_t fixed_portion; NTSTATUS status; if (total_params < 2) { @@ -3656,6 +3665,7 @@ static void call_trans2qfsinfo(connection_struct *conn, info_level, req->flags2, max_data_bytes, + &fixed_portion, NULL, ppdata, &data_len); if (!NT_STATUS_IS_OK(status)) { -- 1.8.4 From 13267d9765bd6d52e1dff3b7eca9619f63c8e7a1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 27 Aug 2013 09:36:03 +0000 Subject: [PATCH 09/13] smbd: Correctly return INFO_LENGTH_MISMATCH in smb2_getinfo We have to return this error if the client offered less than the fixed portion of the infolevel data requires Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106 Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 91939614760837b2ac2c6bb8b5daac108a4f4670) --- source3/smbd/smb2_getinfo.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index 698e775..c6a1433 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -392,6 +392,12 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, tevent_req_nterror(req, status); return tevent_req_post(req, ev); } + if (in_output_buffer_length < fixed_portion) { + SAFE_FREE(data); + tevent_req_nterror( + req, NT_STATUS_INFO_LENGTH_MISMATCH); + return tevent_req_post(req, ev); + } if (data_size > 0) { state->out_output_buffer = data_blob_talloc(state, data, @@ -434,6 +440,12 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, tevent_req_nterror(req, status); return tevent_req_post(req, ev); } + if (in_output_buffer_length < fixed_portion) { + SAFE_FREE(data); + tevent_req_nterror( + req, NT_STATUS_INFO_LENGTH_MISMATCH); + return tevent_req_post(req, ev); + } if (data_size > 0) { state->out_output_buffer = data_blob_talloc(state, data, -- 1.8.4 From d0dfcdae762fd771bab5f483cb67b98477cddb5c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 27 Aug 2013 09:37:34 +0000 Subject: [PATCH 10/13] smbd: Correctly return BUFFER_OVERFLOW in smb2_getinfo Also, don't overflow the client buffer Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106 Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 40f60024ca19e33cbbe9825b42692f386a8f1dd9) --- source3/smbd/smb2_getinfo.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index c6a1433..4111aa1 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -406,6 +406,11 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, if (tevent_req_nomem(state->out_output_buffer.data, req)) { return tevent_req_post(req, ev); } + if (data_size > in_output_buffer_length) { + state->out_output_buffer.length = + in_output_buffer_length; + status = STATUS_BUFFER_OVERFLOW; + } } SAFE_FREE(data); break; @@ -454,6 +459,11 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, if (tevent_req_nomem(state->out_output_buffer.data, req)) { return tevent_req_post(req, ev); } + if (data_size > in_output_buffer_length) { + state->out_output_buffer.length = + in_output_buffer_length; + status = STATUS_BUFFER_OVERFLOW; + } } SAFE_FREE(data); break; -- 1.8.4 From 10a2d0421234d7fc144666440be703c0e059b504 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 27 Aug 2013 09:38:29 +0000 Subject: [PATCH 11/13] smbd: Revert a93f9c3 This was too broad and has been replaced by finer-grained error checks Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106 Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit b37edda32930fec372d6467d442f67532c3fbd33) --- source3/smbd/smb2_getinfo.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index 4111aa1..449aeb3 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -530,11 +530,6 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - if (state->out_output_buffer.length > in_output_buffer_length) { - tevent_req_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH); - return tevent_req_post(req, ev); - } - state->status = status; tevent_req_done(req); return tevent_req_post(req, ev); -- 1.8.4 From c1459dafd159bea048e391629c43e1c18eaaff88 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 27 Aug 2013 09:39:17 +0000 Subject: [PATCH 12/13] smbd: Fix error return for STREAM_INFO The stream_info marshalling follows its own rules. This needs unifying eventually... Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106 Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 5634f240fd4273cb7327111140ccbea0fd41e3fc) --- source3/smbd/trans2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bb9e98d..101adea 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4229,6 +4229,10 @@ static NTSTATUS marshall_stream_info(unsigned int num_streams, unsigned int i; unsigned int ofs = 0; + if (max_data_bytes < 32) { + return NT_STATUS_INFO_LENGTH_MISMATCH; + } + for (i = 0; i < num_streams; i++) { unsigned int next_offset; size_t namelen; -- 1.8.4 From e06fd1369c24b1665a6f4b07672ddd352bdd2627 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 27 Aug 2013 09:40:19 +0000 Subject: [PATCH 13/13] smbd: Correctly return INFO_LENGTH_MISMATCH for smb1 This is required if the client offered less buffer than the fixed portion of the info level data requires Bug: https://bugzilla.samba.org/show_bug.cgi?id=10106 Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 1b1935b876a14154ef74e447bf53eb7cd0a5dde9) --- source3/smbd/trans2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 101adea..2f2bbf6 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5589,6 +5589,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd reply_nterror(req, status); return; } + if (fixed_portion > max_data_bytes) { + reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH); + return; + } send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size, max_data_bytes); -- 1.8.4