diff options
Diffstat (limited to 'source4/smb_server/smb2')
-rw-r--r-- | source4/smb_server/smb2/fileinfo.c | 2 | ||||
-rw-r--r-- | source4/smb_server/smb2/fileio.c | 6 | ||||
-rw-r--r-- | source4/smb_server/smb2/keepalive.c | 9 | ||||
-rw-r--r-- | source4/smb_server/smb2/negprot.c | 4 | ||||
-rw-r--r-- | source4/smb_server/smb2/receive.c | 41 | ||||
-rw-r--r-- | source4/smb_server/smb2/smb2_server.h | 3 |
6 files changed, 57 insertions, 8 deletions
diff --git a/source4/smb_server/smb2/fileinfo.c b/source4/smb_server/smb2/fileinfo.c index 6c4b8f33d5..82b006c4a1 100644 --- a/source4/smb_server/smb2/fileinfo.c +++ b/source4/smb_server/smb2/fileinfo.c @@ -369,7 +369,7 @@ void smb2srv_setinfo_recv(struct smb2srv_request *req) SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_setinfo_send, NTVFS_ASYNC_STATE_MAY_ASYNC); info->in.level = SVAL(req->in.body, 0x02); - SMB2SRV_CHECK(smb2_pull_s32o32_blob(&req->in, info, req->in.body+0x04, &info->in.blob)); + SMB2SRV_CHECK(smb2_pull_s32o16_blob(&req->in, info, req->in.body+0x04, &info->in.blob)); info->in.flags = IVAL(req->in.body, 0x0C); info->in.file.ntvfs = smb2srv_pull_handle(req, req->in.body, 0x10); diff --git a/source4/smb_server/smb2/fileio.c b/source4/smb_server/smb2/fileio.c index 2c322ea587..4f4402ba33 100644 --- a/source4/smb_server/smb2/fileio.c +++ b/source4/smb_server/smb2/fileio.c @@ -254,6 +254,12 @@ void smb2srv_read_recv(struct smb2srv_request *req) union smb_read *io; SMB2SRV_CHECK_BODY_SIZE(req, 0x30, true); + + /* MS-SMB2 2.2.19 read must have a single byte of zero */ + if (req->in.body_size - req->in.body_fixed < 1) { + smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER); + return; + } SMB2SRV_TALLOC_IO_PTR(io, union smb_read); SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_read_send, NTVFS_ASYNC_STATE_MAY_ASYNC); diff --git a/source4/smb_server/smb2/keepalive.c b/source4/smb_server/smb2/keepalive.c index f40bcc485c..ff47d594f0 100644 --- a/source4/smb_server/smb2/keepalive.c +++ b/source4/smb_server/smb2/keepalive.c @@ -54,8 +54,13 @@ void smb2srv_keepalive_recv(struct smb2srv_request *req) { uint16_t _pad; - if (req->in.body_size < 0x04) { - smb2srv_send_error(req, NT_STATUS_FOOBAR); + if (req->in.body_size != 0x04) { + smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + if (SVAL(req->in.body, 0x00) != 0x04) { + smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER); return; } diff --git a/source4/smb_server/smb2/negprot.c b/source4/smb_server/smb2/negprot.c index d64b36d659..49a2d12ef4 100644 --- a/source4/smb_server/smb2/negprot.c +++ b/source4/smb_server/smb2/negprot.c @@ -192,7 +192,7 @@ void smb2srv_negprot_recv(struct smb2srv_request *req) enum ndr_err_code ndr_err; if (req->in.body_size < 0x26) { - smb2srv_send_error(req, NT_STATUS_FOOBAR); + smbsrv_terminate_connection(req->smb_conn, "Bad body size in SMB2 negprot"); return; } @@ -209,7 +209,7 @@ void smb2srv_negprot_recv(struct smb2srv_request *req) io->in.capabilities = IVAL(req->in.body, 0x08); ndr_err = smbcli_pull_guid(req->in.body, 0xC, &io->in.client_guid); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - smbsrv_terminate_connection(req->smb_conn, nt_errstr(NT_STATUS_FOOBAR)); + smbsrv_terminate_connection(req->smb_conn, "Bad GUID in SMB2 negprot"); talloc_free(req); return; } diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 1fe6f0b877..c3607f0a33 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -153,7 +153,7 @@ static void smb2srv_chain_reply(struct smb2srv_request *p_req) chain_offset = p_req->chain_offset; p_req->chain_offset = 0; - if (p_req->in.size < (NBT_HDR_SIZE + chain_offset + SMB2_MIN_SIZE)) { + if (p_req->in.size < (NBT_HDR_SIZE + chain_offset + SMB2_MIN_SIZE_NO_BODY)) { DEBUG(2,("Invalid SMB2 chained packet at offset 0x%X\n", chain_offset)); smbsrv_terminate_connection(p_req->smb_conn, "Invalid SMB2 chained packet"); @@ -184,6 +184,19 @@ static void smb2srv_chain_reply(struct smb2srv_request *p_req) req->in.body_size = req->in.size - (NBT_HDR_SIZE+ chain_offset + SMB2_HDR_BODY); req->in.dynamic = NULL; + req->seqnum = BVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID); + + if (req->in.body_size < 2) { + /* error handling for this is different for negprot to + other packet types */ + uint16_t opcode = SVAL(req->in.hdr, SMB2_HDR_OPCODE); + if (opcode == SMB2_OP_NEGPROT) { + smbsrv_terminate_connection(req->smb_conn, "Bad body size in SMB2 negprot"); + } else { + smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER); + } + } + buffer_code = SVAL(req->in.body, 0); req->in.body_fixed = (buffer_code & ~1); dynamic_size = req->in.body_size - req->in.body_fixed; @@ -290,6 +303,10 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) uint64_t uid; uint32_t flags; + if (SVAL(req->in.hdr, SMB2_HDR_LENGTH) != SMB2_HDR_BODY) { + smbsrv_terminate_connection(req->smb_conn, "Invalid SMB2 header length"); + return NT_STATUS_INVALID_PARAMETER; + } opcode = SVAL(req->in.hdr, SMB2_HDR_OPCODE); req->chain_offset = IVAL(req->in.hdr, SMB2_HDR_NEXT_COMMAND); req->seqnum = BVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID); @@ -297,6 +314,13 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) uid = BVAL(req->in.hdr, SMB2_HDR_SESSION_ID); flags = IVAL(req->in.hdr, SMB2_HDR_FLAGS); + if (req->smb_conn->highest_smb2_seqnum != 0 && + req->seqnum <= req->smb_conn->highest_smb2_seqnum) { + smbsrv_terminate_connection(req->smb_conn, "Invalid SMB2 sequence number"); + return NT_STATUS_INVALID_PARAMETER; + } + req->smb_conn->highest_smb2_seqnum = req->seqnum; + req->session = smbsrv_session_find(req->smb_conn, uid, req->request_time); req->tcon = smbsrv_smb2_tcon_find(req->session, tid, req->request_time); @@ -443,7 +467,7 @@ NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob) return NT_STATUS_OK; } - if (blob.length < (NBT_HDR_SIZE + SMB2_MIN_SIZE)) { + if (blob.length < (NBT_HDR_SIZE + SMB2_MIN_SIZE_NO_BODY)) { DEBUG(2,("Invalid SMB2 packet length count %ld\n", (long)blob.length)); smbsrv_terminate_connection(smb_conn, "Invalid SMB2 packet"); return NT_STATUS_OK; @@ -470,6 +494,19 @@ NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob) req->in.body_size = req->in.size - (SMB2_HDR_BODY+NBT_HDR_SIZE); req->in.dynamic = NULL; + req->seqnum = BVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID); + + if (req->in.body_size < 2) { + /* error handling for this is different for negprot to + other packet types */ + uint16_t opcode = SVAL(req->in.hdr, SMB2_HDR_OPCODE); + if (opcode == SMB2_OP_NEGPROT) { + smbsrv_terminate_connection(req->smb_conn, "Bad body size in SMB2 negprot"); + } else { + smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER); + } + } + buffer_code = SVAL(req->in.body, 0); req->in.body_fixed = (buffer_code & ~1); dynamic_size = req->in.body_size - req->in.body_fixed; diff --git a/source4/smb_server/smb2/smb2_server.h b/source4/smb_server/smb2/smb2_server.h index d45e0861af..431add4ed9 100644 --- a/source4/smb_server/smb2/smb2_server.h +++ b/source4/smb_server/smb2/smb2_server.h @@ -75,7 +75,7 @@ struct smbsrv_request; /* useful way of catching field size errors with file and line number */ #define SMB2SRV_CHECK_BODY_SIZE(req, size, dynamic) do { \ size_t is_size = req->in.body_size; \ - uint16_t field_size = SVAL(req->in.body, 0); \ + uint16_t field_size; \ uint16_t want_size = ((dynamic)?(size)+1:(size)); \ if (is_size < (size)) { \ DEBUG(0,("%s: buffer too small 0x%x. Expected 0x%x\n", \ @@ -83,6 +83,7 @@ struct smbsrv_request; smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER); \ return; \ }\ + field_size = SVAL(req->in.body, 0); \ if (field_size != want_size) { \ DEBUG(0,("%s: unexpected fixed body size 0x%x. Expected 0x%x\n", \ __location__, (unsigned)field_size, (unsigned)want_size)); \ |