From 910d61bcd1fbfc6fc406d4384f305f5210e92d56 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 18 Nov 2005 14:13:49 +0000 Subject: r11789: - add the start of a SMB2 server - it does Negprot and SessionSetup yet the rest returns NT_STATUS_NOT_IMPLEMENTED - it's off by default, enable with: smbsrv:enable smb2 = yes - negotition in the SMB Negprot isn't supported yet - it's only tested with smbtorture SMB2-CONNECT not with vista as client metze (This used to be commit 08b31d5f618d2e416cb9812ad3a49754cd7212b8) --- source4/smb_server/smb2/receive.c | 269 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 source4/smb_server/smb2/receive.c (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c new file mode 100644 index 0000000000..87b480ee64 --- /dev/null +++ b/source4/smb_server/smb2/receive.c @@ -0,0 +1,269 @@ +/* + Unix SMB2 implementation. + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Stefan Metzmacher 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "system/time.h" +#include "smbd/service_stream.h" +#include "libcli/smb2/smb2.h" +#include "smb_server/smb_server.h" +#include "smb_server/smb2/smb2_server.h" +#include "lib/stream/packet.h" + + +static struct smb2srv_request *smb2srv_init_request(struct smbsrv_connection *smb_conn) +{ + struct smb2srv_request *req; + + req = talloc_zero(smb_conn, struct smb2srv_request); + if (!req) return NULL; + + req->smb_conn = smb_conn; + + return req; +} + +NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint_t body_fixed_size, uint_t body_dynamic_size) +{ + req->out.size = SMB2_HDR_BODY+NBT_HDR_SIZE+body_fixed_size; + + req->out.allocated = req->out.size + body_dynamic_size; + req->out.buffer = talloc_size(req, req->out.allocated); + NT_STATUS_HAVE_NO_MEMORY(req->out.buffer); + + req->out.hdr = req->out.buffer + NBT_HDR_SIZE; + req->out.body = req->out.hdr + SMB2_HDR_BODY; + req->out.body_size = body_fixed_size; + req->out.dynamic = (body_dynamic_size ? req->out.body + body_fixed_size : NULL); + + SIVAL(req->out.hdr, 0, SMB2_MAGIC); + SSVAL(req->out.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY); + SSVAL(req->out.hdr, SMB2_HDR_PAD1, 0); + SIVAL(req->out.hdr, SMB2_HDR_STATUS, 0); + SSVAL(req->out.hdr, SMB2_HDR_OPCODE, SVAL(req->in.hdr, SMB2_HDR_OPCODE)); + SSVAL(req->out.hdr, SMB2_HDR_PAD2, 0); + SIVAL(req->out.hdr, SMB2_HDR_FLAGS, 0x00000001); + SIVAL(req->out.hdr, SMB2_HDR_UNKNOWN, 0); + SBVAL(req->out.hdr, SMB2_HDR_SEQNUM, req->seqnum); + SIVAL(req->out.hdr, SMB2_HDR_PID, IVAL(req->in.hdr, SMB2_HDR_PID)); + SIVAL(req->out.hdr, SMB2_HDR_TID, IVAL(req->in.hdr, SMB2_HDR_TID)); + SBVAL(req->out.hdr, SMB2_HDR_UID, BVAL(req->in.hdr, SMB2_HDR_UID)); + memset(req->out.hdr+SMB2_HDR_SIG, 0, 16); + + /* set the length of the fixed body part and +1 if there's a dynamic part also */ + SSVAL(req->out.body, 0, body_fixed_size + (body_dynamic_size?1:0)); + + /* + * if we have a dynamic part, make sure the first byte + * which is always be part of the packet is initialized + */ + if (body_dynamic_size) { + SCVAL(req->out.dynamic, 0, 0); + } + + return NT_STATUS_OK; +} + +void smb2srv_send_reply(struct smb2srv_request *req) +{ + DATA_BLOB blob; + NTSTATUS status; + + if (req->out.size > NBT_HDR_SIZE) { + _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE); + } + + blob = data_blob_const(req->out.buffer, req->out.size); + status = packet_send(req->smb_conn->packet, blob); + if (!NT_STATUS_IS_OK(status)) { + smbsrv_terminate_connection(req->smb_conn, nt_errstr(status)); + } + talloc_free(req); +} + +void smb2srv_send_error(struct smb2srv_request *req, NTSTATUS error) +{ + NTSTATUS status; + + status = smb2srv_setup_reply(req, 8, 1); + if (!NT_STATUS_IS_OK(status)) { + smbsrv_terminate_connection(req->smb_conn, nt_errstr(status)); + talloc_free(req); + return; + } + + SIVAL(req->out.hdr, SMB2_HDR_STATUS, NT_STATUS_V(error)); + + SSVAL(req->out.body, 0x02, 0); + SIVAL(req->out.body, 0x04, 0); + + smb2srv_send_reply(req); +} + +static NTSTATUS smb2srv_reply(struct smb2srv_request *req) +{ + uint16_t opcode; + + opcode = SVAL(req->in.hdr, SMB2_HDR_OPCODE); + req->seqnum = BVAL(req->in.hdr, SMB2_HDR_SEQNUM); + + errno = 0; + + switch (opcode) { + case SMB2_OP_NEGPROT: + smb2srv_negprot_recv(req); + return NT_STATUS_OK; + case SMB2_OP_SESSSETUP: + smb2srv_sesssetup_recv(req); + return NT_STATUS_OK; + case SMB2_OP_TCON: + smb2srv_tcon_recv(req); + return NT_STATUS_OK; + case SMB2_OP_TDIS: + smb2srv_tdis_recv(req); + return NT_STATUS_OK; + case SMB2_OP_CREATE: + smb2srv_create_recv(req); + return NT_STATUS_OK; + case SMB2_OP_CLOSE: + smb2srv_close_recv(req); + return NT_STATUS_OK; + case SMB2_OP_READ: + smb2srv_read_recv(req); + return NT_STATUS_OK; + case SMB2_OP_WRITE: + smb2srv_write_recv(req); + return NT_STATUS_OK; + case SMB2_OP_CANCEL: + smb2srv_cancel_recv(req); + return NT_STATUS_OK; + case SMB2_OP_FIND: + smb2srv_find_recv(req); + return NT_STATUS_OK; + case SMB2_OP_NOTIFY: + smb2srv_notify_recv(req); + return NT_STATUS_OK; + case SMB2_OP_GETINFO: + smb2srv_getinfo_recv(req); + return NT_STATUS_OK; + case SMB2_OP_SETINFO: + smb2srv_setinfo_recv(req); + return NT_STATUS_OK; + case SMB2_OP_BREAK: + smb2srv_break_recv(req); + return NT_STATUS_OK; + } + + DEBUG(1,("Invalid SMB2 opcode: 0x%04X\n", opcode)); + smbsrv_terminate_connection(req->smb_conn, "Invalid SMB2 opcode"); + return NT_STATUS_OK; +} + +NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob) +{ + struct smbsrv_connection *smb_conn = talloc_get_type(private, struct smbsrv_connection); + struct smb2srv_request *req; + uint32_t protocol_version; + uint16_t buffer_code; + uint32_t dynamic_size; + + /* see if its a special NBT packet */ + if (CVAL(blob.data,0) != 0) { + DEBUG(2,("Special NBT packet on SMB2 connection")); + smbsrv_terminate_connection(smb_conn, "Special NBT packet on SMB2 connection"); + return NT_STATUS_OK; + } + + if (blob.length < (NBT_HDR_SIZE + SMB2_MIN_SIZE)) { + DEBUG(2,("Invalid SMB2 packet length count %d\n", blob.length)); + smbsrv_terminate_connection(smb_conn, "Invalid SMB2 packet"); + return NT_STATUS_OK; + } + + protocol_version = IVAL(blob.data, NBT_HDR_SIZE); + + if (protocol_version != SMB2_MAGIC) { + DEBUG(2,("Invalid SMB packet: protocl prefix: 0x%08X\n", protocol_version)); + smbsrv_terminate_connection(smb_conn, "NON-SMB2 packet"); + return NT_STATUS_OK; + } + + req = smb2srv_init_request(smb_conn); + NT_STATUS_HAVE_NO_MEMORY(req); + + req->in.buffer = talloc_steal(req, blob.data); + req->in.size = blob.length; + req->request_time = timeval_current(); + req->in.allocated = req->in.size; + + req->in.hdr = req->in.buffer+ NBT_HDR_SIZE; + req->in.body = req->in.hdr + SMB2_HDR_BODY; + req->in.body_size = req->in.size - (SMB2_HDR_BODY+NBT_HDR_SIZE); + req->in.dynamic = NULL; + + buffer_code = SVAL(req->in.body, 0); + dynamic_size = req->in.body_size - (buffer_code & ~1); + + if (dynamic_size != 0 && (buffer_code & 1)) { + req->in.dynamic = req->in.body + (buffer_code & ~1); + if (smb2_oob(&req->in, req->in.dynamic, dynamic_size)) { + DEBUG(1,("SMB2 request invalid dynamic size 0x%x\n", + dynamic_size)); + smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER); + return NT_STATUS_OK; + } + } + + /* + * TODO: - make sure the length field is 64 + * - make sure it's a request + */ + + return smb2srv_reply(req); +} + +/* + * init the SMB2 protocol related stuff + */ +NTSTATUS smbsrv_init_smb2_connection(struct smbsrv_connection *smb_conn) +{ + NTSTATUS status; + + /* now initialise a few default values associated with this smb socket */ + smb_conn->negotiate.max_send = 0xFFFF; + + /* this is the size that w2k uses, and it appears to be important for + good performance */ + smb_conn->negotiate.max_recv = lp_max_xmit(); + + smb_conn->negotiate.zone_offset = get_time_zone(time(NULL)); + + smb_conn->config.security = SEC_USER; + smb_conn->config.nt_status_support = True; + + status = smbsrv_init_sessions(smb_conn, UINT64_MAX); + NT_STATUS_NOT_OK_RETURN(status); + + status = smbsrv_init_tcons(smb_conn, UINT32_MAX); + NT_STATUS_NOT_OK_RETURN(status); + + return NT_STATUS_OK; + +} -- cgit From b9b59fa7984c4f800c177a235a984e05d59f1ef8 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 30 Nov 2005 03:20:25 +0000 Subject: r11968: More warning fixes. We're on track to getting to double digits for the number of warnings generated now. (This used to be commit d479f2d7607adc698d71c5ba26932c72a26dcaab) --- source4/smb_server/smb2/receive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 87b480ee64..9afa10463f 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -192,7 +192,7 @@ NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob) } if (blob.length < (NBT_HDR_SIZE + SMB2_MIN_SIZE)) { - DEBUG(2,("Invalid SMB2 packet length count %d\n", blob.length)); + DEBUG(2,("Invalid SMB2 packet length count %ld\n", (long)blob.length)); smbsrv_terminate_connection(smb_conn, "Invalid SMB2 packet"); return NT_STATUS_OK; } -- cgit From 2634f22bfcd5172ae20e9fa0d236aee91c43c1ae Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Dec 2005 13:26:24 +0000 Subject: r12092: - add dummy functions for the missing SMB2 opcodes - implement keepalive and logoff metze (This used to be commit 859ab627f45a5acca1deb66b8abdc38eaf49e5a2) --- source4/smb_server/smb2/receive.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 9afa10463f..7544e0be3e 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -56,7 +56,7 @@ NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint_t body_fixed_size SIVAL(req->out.hdr, 0, SMB2_MAGIC); SSVAL(req->out.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY); SSVAL(req->out.hdr, SMB2_HDR_PAD1, 0); - SIVAL(req->out.hdr, SMB2_HDR_STATUS, 0); + SIVAL(req->out.hdr, SMB2_HDR_STATUS, NT_STATUS_V(req->status)); SSVAL(req->out.hdr, SMB2_HDR_OPCODE, SVAL(req->in.hdr, SMB2_HDR_OPCODE)); SSVAL(req->out.hdr, SMB2_HDR_PAD2, 0); SIVAL(req->out.hdr, SMB2_HDR_FLAGS, 0x00000001); @@ -133,6 +133,9 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) case SMB2_OP_SESSSETUP: smb2srv_sesssetup_recv(req); return NT_STATUS_OK; + case SMB2_OP_LOGOFF: + smb2srv_logoff_recv(req); + return NT_STATUS_OK; case SMB2_OP_TCON: smb2srv_tcon_recv(req); return NT_STATUS_OK; @@ -145,15 +148,27 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) case SMB2_OP_CLOSE: smb2srv_close_recv(req); return NT_STATUS_OK; + case SMB2_OP_FLUSH: + smb2srv_flush_recv(req); + return NT_STATUS_OK; case SMB2_OP_READ: smb2srv_read_recv(req); return NT_STATUS_OK; case SMB2_OP_WRITE: smb2srv_write_recv(req); return NT_STATUS_OK; + case SMB2_OP_LOCK: + smb2srv_lock_recv(req); + return NT_STATUS_OK; + case SMB2_OP_IOCTL: + smb2srv_ioctl_recv(req); + return NT_STATUS_OK; case SMB2_OP_CANCEL: smb2srv_cancel_recv(req); return NT_STATUS_OK; + case SMB2_OP_KEEPALIVE: + smb2srv_keepalive_recv(req); + return NT_STATUS_OK; case SMB2_OP_FIND: smb2srv_find_recv(req); return NT_STATUS_OK; -- cgit From 6b1ee03c53223fb6adcd8f485808536942bad6b8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Dec 2005 14:17:06 +0000 Subject: r12095: the most SMB2 opcodes need a valid session and tcon, metze (This used to be commit 40b301c6bdb329ad347ac8a474be85dcbc671518) --- source4/smb_server/smb2/receive.c | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 7544e0be3e..66ebe162cf 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -120,12 +120,21 @@ void smb2srv_send_error(struct smb2srv_request *req, NTSTATUS error) static NTSTATUS smb2srv_reply(struct smb2srv_request *req) { uint16_t opcode; + uint32_t tid; + uint64_t uid; opcode = SVAL(req->in.hdr, SMB2_HDR_OPCODE); req->seqnum = BVAL(req->in.hdr, SMB2_HDR_SEQNUM); + tid = IVAL(req->in.hdr, SMB2_HDR_TID); + uid = BVAL(req->in.hdr, SMB2_HDR_UID); + + req->session = smbsrv_session_find(req->smb_conn, uid); + req->tcon = smbsrv_tcon_find(req->smb_conn, tid); errno = 0; + /* TODO: check the seqnum */ + switch (opcode) { case SMB2_OP_NEGPROT: smb2srv_negprot_recv(req); @@ -134,54 +143,84 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) smb2srv_sesssetup_recv(req); return NT_STATUS_OK; case SMB2_OP_LOGOFF: + if (!req->session) goto nosession; smb2srv_logoff_recv(req); return NT_STATUS_OK; case SMB2_OP_TCON: + if (!req->session) goto nosession; smb2srv_tcon_recv(req); return NT_STATUS_OK; case SMB2_OP_TDIS: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_tdis_recv(req); return NT_STATUS_OK; case SMB2_OP_CREATE: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_create_recv(req); return NT_STATUS_OK; case SMB2_OP_CLOSE: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_close_recv(req); return NT_STATUS_OK; case SMB2_OP_FLUSH: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_flush_recv(req); return NT_STATUS_OK; case SMB2_OP_READ: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_read_recv(req); return NT_STATUS_OK; case SMB2_OP_WRITE: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_write_recv(req); return NT_STATUS_OK; case SMB2_OP_LOCK: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_lock_recv(req); return NT_STATUS_OK; case SMB2_OP_IOCTL: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_ioctl_recv(req); return NT_STATUS_OK; case SMB2_OP_CANCEL: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_cancel_recv(req); return NT_STATUS_OK; case SMB2_OP_KEEPALIVE: smb2srv_keepalive_recv(req); return NT_STATUS_OK; case SMB2_OP_FIND: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_find_recv(req); return NT_STATUS_OK; case SMB2_OP_NOTIFY: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_notify_recv(req); return NT_STATUS_OK; case SMB2_OP_GETINFO: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_getinfo_recv(req); return NT_STATUS_OK; case SMB2_OP_SETINFO: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_setinfo_recv(req); return NT_STATUS_OK; case SMB2_OP_BREAK: + if (!req->session) goto nosession; + if (!req->tcon) goto notcon; smb2srv_break_recv(req); return NT_STATUS_OK; } @@ -189,6 +228,13 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) DEBUG(1,("Invalid SMB2 opcode: 0x%04X\n", opcode)); smbsrv_terminate_connection(req->smb_conn, "Invalid SMB2 opcode"); return NT_STATUS_OK; + +nosession: + smb2srv_send_error(req, NT_STATUS_USER_SESSION_DELETED); + return NT_STATUS_OK; +notcon: + smb2srv_send_error(req, NT_STATUS_NETWORK_NAME_DELETED); + return NT_STATUS_OK; } NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob) -- cgit From 273f340376452bd072b68d0601dde3f7b43b62db Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Dec 2005 17:59:20 +0000 Subject: r12102: for SMB2 we need to allocate tcons per session metze (This used to be commit 4d527ac005086c2db954578b4126ca128e436e01) --- source4/smb_server/smb2/receive.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 66ebe162cf..310ded5355 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -129,7 +129,7 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) uid = BVAL(req->in.hdr, SMB2_HDR_UID); req->session = smbsrv_session_find(req->smb_conn, uid); - req->tcon = smbsrv_tcon_find(req->smb_conn, tid); + req->tcon = smbsrv_smb2_tcon_find(req->session, tid); errno = 0; @@ -322,9 +322,6 @@ NTSTATUS smbsrv_init_smb2_connection(struct smbsrv_connection *smb_conn) status = smbsrv_init_sessions(smb_conn, UINT64_MAX); NT_STATUS_NOT_OK_RETURN(status); - status = smbsrv_init_tcons(smb_conn, UINT32_MAX); - NT_STATUS_NOT_OK_RETURN(status); - return NT_STATUS_OK; } -- cgit From d4de4c2d210d2e8c9b5aedf70695594809ad6a0b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 30 Dec 2005 13:16:54 +0000 Subject: r12608: Remove some unused #include lines. (This used to be commit 70e7449318aa0e9d2639c76730a7d1683b2f4981) --- source4/smb_server/smb2/receive.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 310ded5355..f0e21473ba 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -21,7 +21,6 @@ #include "includes.h" #include "system/time.h" -#include "smbd/service_stream.h" #include "libcli/smb2/smb2.h" #include "smb_server/smb_server.h" #include "smb_server/smb2/smb2_server.h" -- cgit From 63d718e243fd03e6ea24c47e7442975ec088a5b5 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 3 Jan 2006 17:27:33 +0000 Subject: r12696: Reduce the size of include/structs.h (This used to be commit 63917616016133c623fc6ff59454bc313ee7dd8f) --- source4/smb_server/smb2/receive.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index f0e21473ba..a1f12f84c0 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -22,6 +22,7 @@ #include "includes.h" #include "system/time.h" #include "libcli/smb2/smb2.h" +#include "libcli/smb2/smb2_calls.h" #include "smb_server/smb_server.h" #include "smb_server/smb2/smb2_server.h" #include "lib/stream/packet.h" -- cgit From db04cffbbfe15a52b954960ff0eb40d2a5e4f00d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 5 Jan 2006 16:43:56 +0000 Subject: r12725: some minor updates metze (This used to be commit f2e97983f278211c6d70400ce1f43d6a69df0d8a) --- source4/smb_server/smb2/receive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index a1f12f84c0..ef67d29c51 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -87,7 +87,7 @@ void smb2srv_send_reply(struct smb2srv_request *req) NTSTATUS status; if (req->out.size > NBT_HDR_SIZE) { - _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE); + _smb2_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE); } blob = data_blob_const(req->out.buffer, req->out.size); -- cgit From 316269a07523a421755158540d2f4e22fa312866 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 26 Mar 2006 11:32:27 +0000 Subject: r14739: keep the last request time for the smbsrv_connection, smbsrv_session and smbsrv_tcon for management tools metze (This used to be commit 2c87f210e9e68de42dc45ca6532f3f33f4b6ce95) --- source4/smb_server/smb2/receive.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index ef67d29c51..6781b6ce65 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -128,8 +128,8 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) tid = IVAL(req->in.hdr, SMB2_HDR_TID); uid = BVAL(req->in.hdr, SMB2_HDR_UID); - req->session = smbsrv_session_find(req->smb_conn, uid); - req->tcon = smbsrv_smb2_tcon_find(req->session, tid); + req->session = smbsrv_session_find(req->smb_conn, uid, req->request_time); + req->tcon = smbsrv_smb2_tcon_find(req->session, tid, req->request_time); errno = 0; @@ -241,10 +241,13 @@ NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob) { struct smbsrv_connection *smb_conn = talloc_get_type(private, struct smbsrv_connection); struct smb2srv_request *req; + struct timeval cur_time = timeval_current(); uint32_t protocol_version; uint16_t buffer_code; uint32_t dynamic_size; + smb_conn->statistics.last_request_time = cur_time; + /* see if its a special NBT packet */ if (CVAL(blob.data,0) != 0) { DEBUG(2,("Special NBT packet on SMB2 connection")); @@ -271,7 +274,7 @@ NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob) req->in.buffer = talloc_steal(req, blob.data); req->in.size = blob.length; - req->request_time = timeval_current(); + req->request_time = cur_time; req->in.allocated = req->in.size; req->in.hdr = req->in.buffer+ NBT_HDR_SIZE; -- cgit From 0eddf14b307e905663b95296aa695a10d3fb90f7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 24 Apr 2006 09:36:09 +0000 Subject: r15191: Avoid uint_t as it's not standard. (This used to be commit 7af59357b94e3819415b3a9257be0ced745ce130) --- source4/smb_server/smb2/receive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 6781b6ce65..46923988bb 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -40,7 +40,7 @@ static struct smb2srv_request *smb2srv_init_request(struct smbsrv_connection *sm return req; } -NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint_t body_fixed_size, uint_t body_dynamic_size) +NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint_t body_fixed_size, size_t body_dynamic_size) { req->out.size = SMB2_HDR_BODY+NBT_HDR_SIZE+body_fixed_size; -- cgit From bc141c795767cc765731c607f1fb047811da6e03 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 28 Apr 2006 01:55:17 +0000 Subject: r15304: Fix smbd build, more updates on getting --enable-dso to build again (This used to be commit 3ef9326386ba1c210166302cbcf02d2ed3f19944) --- source4/smb_server/smb2/receive.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 46923988bb..e27e622a4a 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -24,6 +24,7 @@ #include "libcli/smb2/smb2.h" #include "libcli/smb2/smb2_calls.h" #include "smb_server/smb_server.h" +#include "smb_server/service_smb_proto.h" #include "smb_server/smb2/smb2_server.h" #include "lib/stream/packet.h" -- cgit From dc86ab3e454d7219608d01879145dec5609acaa3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 11 May 2006 10:47:37 +0000 Subject: r15532: add a BOOL body_dynamic_present, because the body_dynamic_size can be 0 also if the dynamic flag should be set metze (This used to be commit 7829100e1ee79f4f5d24004af221288e19c09b3e) --- source4/smb_server/smb2/receive.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index e27e622a4a..abd825adcc 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -41,8 +41,17 @@ static struct smb2srv_request *smb2srv_init_request(struct smbsrv_connection *sm return req; } -NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint_t body_fixed_size, size_t body_dynamic_size) +NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_size, + BOOL body_dynamic_present, uint32_t body_dynamic_size) { + if (body_dynamic_present) { + if (body_dynamic_size == 0) { + body_dynamic_size = 1; + } + } else { + body_dynamic_size = 0; + } + req->out.size = SMB2_HDR_BODY+NBT_HDR_SIZE+body_fixed_size; req->out.allocated = req->out.size + body_dynamic_size; @@ -103,7 +112,7 @@ void smb2srv_send_error(struct smb2srv_request *req, NTSTATUS error) { NTSTATUS status; - status = smb2srv_setup_reply(req, 8, 1); + status = smb2srv_setup_reply(req, 8, True, 0); if (!NT_STATUS_IS_OK(status)) { smbsrv_terminate_connection(req->smb_conn, nt_errstr(status)); talloc_free(req); -- cgit From 1911475976de4a54787ac263eb4b15cb3db5eea3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 21 May 2006 10:13:49 +0000 Subject: r15770: when there's a dynamic body, we need to send the first byte even if the dynamic size if 0 metze (This used to be commit c7e8e79d75fd53fa37e9220e5bc9cac7ab574ff6) --- source4/smb_server/smb2/receive.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index abd825adcc..ac1f691f8a 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -85,6 +85,7 @@ NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_si * which is always be part of the packet is initialized */ if (body_dynamic_size) { + req->out.size += 1; SCVAL(req->out.dynamic, 0, 0); } -- cgit From bd0dcebe36ea926e2ad9a32a6eb103a88325c930 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 29 Jun 2006 23:11:07 +0000 Subject: r16705: fix a bug found by valgrind... as we setup the 1 padding byte for non present dynamic part, we need to overwrite it when we're getting a real dynamic part, so we need to remove the buf->size +=1 when we do the first push to the dynamic part (when buf->dynamic is still but->body + buf->body_fixed) metze (This used to be commit f309209629ad1b63a76fc06163a3eeb07dce4c86) --- source4/smb_server/smb2/receive.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index ac1f691f8a..8ac90b89f9 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -60,6 +60,7 @@ NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_si req->out.hdr = req->out.buffer + NBT_HDR_SIZE; req->out.body = req->out.hdr + SMB2_HDR_BODY; + req->out.body_fixed = body_fixed_size; req->out.body_size = body_fixed_size; req->out.dynamic = (body_dynamic_size ? req->out.body + body_fixed_size : NULL); @@ -294,10 +295,11 @@ NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob) req->in.dynamic = NULL; buffer_code = SVAL(req->in.body, 0); - dynamic_size = req->in.body_size - (buffer_code & ~1); + req->in.body_fixed = (buffer_code & ~1); + dynamic_size = req->in.body_size - req->in.body_fixed; if (dynamic_size != 0 && (buffer_code & 1)) { - req->in.dynamic = req->in.body + (buffer_code & ~1); + req->in.dynamic = req->in.body + req->in.body_fixed; if (smb2_oob(&req->in, req->in.dynamic, dynamic_size)) { DEBUG(1,("SMB2 request invalid dynamic size 0x%x\n", dynamic_size)); -- cgit From 6acd9aed93b09b74e53a3b854085c6c8fab41819 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 1 Jul 2006 14:14:11 +0000 Subject: r16734: the 2 bytes after the opcode and before the flags, is no padding... the following patch is needed for vista beta2 to connect to samba4 metze (This used to be commit 58baae8fc463cd2c4e4ce532c153ad80313b03eb) --- source4/smb_server/smb2/receive.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 8ac90b89f9..80b626a78a 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -69,9 +69,9 @@ NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_si SSVAL(req->out.hdr, SMB2_HDR_PAD1, 0); SIVAL(req->out.hdr, SMB2_HDR_STATUS, NT_STATUS_V(req->status)); SSVAL(req->out.hdr, SMB2_HDR_OPCODE, SVAL(req->in.hdr, SMB2_HDR_OPCODE)); - SSVAL(req->out.hdr, SMB2_HDR_PAD2, 0); + SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1,0x0001); SIVAL(req->out.hdr, SMB2_HDR_FLAGS, 0x00000001); - SIVAL(req->out.hdr, SMB2_HDR_UNKNOWN, 0); + SIVAL(req->out.hdr, SMB2_HDR_UNKNOWN2,0); SBVAL(req->out.hdr, SMB2_HDR_SEQNUM, req->seqnum); SIVAL(req->out.hdr, SMB2_HDR_PID, IVAL(req->in.hdr, SMB2_HDR_PID)); SIVAL(req->out.hdr, SMB2_HDR_TID, IVAL(req->in.hdr, SMB2_HDR_TID)); -- cgit From 39b7ae11ace37241e4d9b710a85b3428ac234219 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 Jul 2006 15:46:36 +0000 Subject: r17012: don't try to send any data when the socket is gone already... (fixes crash bugs) metze (This used to be commit b7418aec33033577de2420c70a8b94a2fb7901dd) --- source4/smb_server/smb2/receive.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 80b626a78a..0f8eb101cf 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -26,6 +26,7 @@ #include "smb_server/smb_server.h" #include "smb_server/service_smb_proto.h" #include "smb_server/smb2/smb2_server.h" +#include "smbd/service_stream.h" #include "lib/stream/packet.h" @@ -98,6 +99,12 @@ void smb2srv_send_reply(struct smb2srv_request *req) DATA_BLOB blob; NTSTATUS status; + if (req->smb_conn->connection->event.fde == NULL) { + /* the socket has been destroyed - no point trying to send a reply! */ + talloc_free(req); + return; + } + if (req->out.size > NBT_HDR_SIZE) { _smb2_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE); } @@ -114,6 +121,12 @@ void smb2srv_send_error(struct smb2srv_request *req, NTSTATUS error) { NTSTATUS status; + if (req->smb_conn->connection->event.fde == NULL) { + /* the socket has been destroyed - no point trying to send an error! */ + talloc_free(req); + return; + } + status = smb2srv_setup_reply(req, 8, True, 0); if (!NT_STATUS_IS_OK(status)) { smbsrv_terminate_connection(req->smb_conn, nt_errstr(status)); -- cgit From 8075ce63fdbaeb2fe508097a46d794a49138c307 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 17 Jul 2006 09:44:13 +0000 Subject: r17084: implement SMB2 Cancel in the server, that makes it possible for clients to cancel async requests, like NOTIFY... metze (This used to be commit eaccd3c4353833daf584aaea4d7e8f11004a8072) --- source4/smb_server/smb2/receive.c | 103 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 5 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 0f8eb101cf..3d6daa51b6 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -28,7 +28,21 @@ #include "smb_server/smb2/smb2_server.h" #include "smbd/service_stream.h" #include "lib/stream/packet.h" +#include "ntvfs/ntvfs.h" +static int smb2srv_request_destructor(struct smb2srv_request *req) +{ + DLIST_REMOVE(req->smb_conn->requests2.list, req); + if (req->pending_id) { + idr_remove(req->smb_conn->requests2.idtree_req, req->pending_id); + } + return 0; +} + +static int smb2srv_request_deny_destructor(struct smb2srv_request *req) +{ + return -1; +} static struct smb2srv_request *smb2srv_init_request(struct smbsrv_connection *smb_conn) { @@ -39,12 +53,24 @@ static struct smb2srv_request *smb2srv_init_request(struct smbsrv_connection *sm req->smb_conn = smb_conn; + talloc_set_destructor(req, smb2srv_request_destructor); + return req; } NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_size, BOOL body_dynamic_present, uint32_t body_dynamic_size) { + uint32_t flags = 0x00000001; + uint32_t pid = IVAL(req->in.hdr, SMB2_HDR_PID); + uint32_t tid = IVAL(req->in.hdr, SMB2_HDR_TID); + + if (req->pending_id) { + flags |= 0x00000002; + pid = req->pending_id; + tid = 0; + } + if (body_dynamic_present) { if (body_dynamic_size == 0) { body_dynamic_size = 1; @@ -71,11 +97,11 @@ NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_si SIVAL(req->out.hdr, SMB2_HDR_STATUS, NT_STATUS_V(req->status)); SSVAL(req->out.hdr, SMB2_HDR_OPCODE, SVAL(req->in.hdr, SMB2_HDR_OPCODE)); SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1,0x0001); - SIVAL(req->out.hdr, SMB2_HDR_FLAGS, 0x00000001); + SIVAL(req->out.hdr, SMB2_HDR_FLAGS, flags); SIVAL(req->out.hdr, SMB2_HDR_UNKNOWN2,0); SBVAL(req->out.hdr, SMB2_HDR_SEQNUM, req->seqnum); - SIVAL(req->out.hdr, SMB2_HDR_PID, IVAL(req->in.hdr, SMB2_HDR_PID)); - SIVAL(req->out.hdr, SMB2_HDR_TID, IVAL(req->in.hdr, SMB2_HDR_TID)); + SIVAL(req->out.hdr, SMB2_HDR_PID, pid); + SIVAL(req->out.hdr, SMB2_HDR_TID, tid); SBVAL(req->out.hdr, SMB2_HDR_UID, BVAL(req->in.hdr, SMB2_HDR_UID)); memset(req->out.hdr+SMB2_HDR_SIG, 0, 16); @@ -216,8 +242,6 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) smb2srv_ioctl_recv(req); return NT_STATUS_OK; case SMB2_OP_CANCEL: - if (!req->session) goto nosession; - if (!req->tcon) goto notcon; smb2srv_cancel_recv(req); return NT_STATUS_OK; case SMB2_OP_KEEPALIVE: @@ -329,6 +353,72 @@ NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob) return smb2srv_reply(req); } +static NTSTATUS smb2srv_init_pending(struct smbsrv_connection *smb_conn) +{ + smb_conn->requests2.idtree_req = idr_init(smb_conn); + NT_STATUS_HAVE_NO_MEMORY(smb_conn->requests2.idtree_req); + smb_conn->requests2.idtree_limit = 0x00FFFFFF & (UINT32_MAX - 1); + smb_conn->requests2.list = NULL; + + return NT_STATUS_OK; +} + +NTSTATUS smb2srv_queue_pending(struct smb2srv_request *req) +{ + int id; + + if (req->pending_id) { + return NT_STATUS_INTERNAL_ERROR; + } + + id = idr_get_new_above(req->smb_conn->requests2.idtree_req, req, + 1, req->smb_conn->requests2.idtree_limit); + if (id == -1) { + return NT_STATUS_INSUFFICIENT_RESOURCES; + } + + DLIST_ADD_END(req->smb_conn->requests2.list, req, struct smb2srv_request *); + req->pending_id = id; + + talloc_set_destructor(req, smb2srv_request_deny_destructor); + smb2srv_send_error(req, STATUS_PENDING); + talloc_set_destructor(req, smb2srv_request_destructor); + + return NT_STATUS_OK; +} + +void smb2srv_cancel_recv(struct smb2srv_request *req) +{ + uint32_t pending_id; + uint32_t flags; + void *p; + struct smb2srv_request *r; + + if (!req->session) goto done; + + flags = IVAL(req->in.hdr, SMB2_HDR_FLAGS); + pending_id = IVAL(req->in.hdr, SMB2_HDR_PID); + + if (!(flags & 0x00000002)) { + /* TODO: what to do here? */ + goto done; + } + + p = idr_find(req->smb_conn->requests2.idtree_req, pending_id); + if (!p) goto done; + + r = talloc_get_type(p, struct smb2srv_request); + if (!r) goto done; + + if (!r->ntvfs) goto done; + + ntvfs_cancel(r->ntvfs); + +done: + /* we never generate a reply for a SMB2 Cancel */ + talloc_free(req); +} + /* * init the SMB2 protocol related stuff */ @@ -351,6 +441,9 @@ NTSTATUS smbsrv_init_smb2_connection(struct smbsrv_connection *smb_conn) status = smbsrv_init_sessions(smb_conn, UINT64_MAX); NT_STATUS_NOT_OK_RETURN(status); + status = smb2srv_init_pending(smb_conn); + NT_STATUS_NOT_OK_RETURN(status); + return NT_STATUS_OK; } -- cgit From 000698d643d4cbffac0f6960f6281c0d4d5df3b9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 19 Sep 2006 21:41:02 +0000 Subject: r18686: Fix typo protocl->protocol (This used to be commit 14b88fefa088b39ca1e6b7d0ef08310d233c6788) --- source4/smb_server/smb2/receive.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 3d6daa51b6..f2a34bdcbf 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -313,7 +313,8 @@ NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob) protocol_version = IVAL(blob.data, NBT_HDR_SIZE); if (protocol_version != SMB2_MAGIC) { - DEBUG(2,("Invalid SMB packet: protocl prefix: 0x%08X\n", protocol_version)); + DEBUG(2,("Invalid SMB packet: protocol prefix: 0x%08X\n", + protocol_version)); smbsrv_terminate_connection(smb_conn, "NON-SMB2 packet"); return NT_STATUS_OK; } -- cgit From bf62b6642c77e14142cdb724dc99dd3f8bfd89ac Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 14 May 2007 18:02:49 +0000 Subject: r22866: handle incoming chained smb2 requests in our server code to let the windows explorer in longhorn beta3 work. metze (This used to be commit 2390c9f24daccec917608cac0870890cdc73cb1c) --- source4/smb_server/smb2/receive.c | 117 ++++++++++++++++++++++++++++++++------ 1 file changed, 100 insertions(+), 17 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index f2a34bdcbf..bae3486014 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -91,18 +91,18 @@ NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_si req->out.body_size = body_fixed_size; req->out.dynamic = (body_dynamic_size ? req->out.body + body_fixed_size : NULL); - SIVAL(req->out.hdr, 0, SMB2_MAGIC); - SSVAL(req->out.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY); - SSVAL(req->out.hdr, SMB2_HDR_PAD1, 0); - SIVAL(req->out.hdr, SMB2_HDR_STATUS, NT_STATUS_V(req->status)); - SSVAL(req->out.hdr, SMB2_HDR_OPCODE, SVAL(req->in.hdr, SMB2_HDR_OPCODE)); - SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1,0x0001); - SIVAL(req->out.hdr, SMB2_HDR_FLAGS, flags); - SIVAL(req->out.hdr, SMB2_HDR_UNKNOWN2,0); - SBVAL(req->out.hdr, SMB2_HDR_SEQNUM, req->seqnum); - SIVAL(req->out.hdr, SMB2_HDR_PID, pid); - SIVAL(req->out.hdr, SMB2_HDR_TID, tid); - SBVAL(req->out.hdr, SMB2_HDR_UID, BVAL(req->in.hdr, SMB2_HDR_UID)); + SIVAL(req->out.hdr, 0, SMB2_MAGIC); + SSVAL(req->out.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY); + SSVAL(req->out.hdr, SMB2_HDR_PAD1, 0); + SIVAL(req->out.hdr, SMB2_HDR_STATUS, NT_STATUS_V(req->status)); + SSVAL(req->out.hdr, SMB2_HDR_OPCODE, SVAL(req->in.hdr, SMB2_HDR_OPCODE)); + SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1, 0x0001); + SIVAL(req->out.hdr, SMB2_HDR_FLAGS, flags); + SIVAL(req->out.hdr, SMB2_HDR_CHAIN_OFFSET, 0); + SBVAL(req->out.hdr, SMB2_HDR_SEQNUM, req->seqnum); + SIVAL(req->out.hdr, SMB2_HDR_PID, pid); + SIVAL(req->out.hdr, SMB2_HDR_TID, tid); + SBVAL(req->out.hdr, SMB2_HDR_UID, BVAL(req->in.hdr, SMB2_HDR_UID)); memset(req->out.hdr+SMB2_HDR_SIG, 0, 16); /* set the length of the fixed body part and +1 if there's a dynamic part also */ @@ -120,6 +120,85 @@ NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_si return NT_STATUS_OK; } +static NTSTATUS smb2srv_reply(struct smb2srv_request *req); + +static void smb2srv_chain_reply(struct smb2srv_request *p_req) +{ + NTSTATUS status; + struct smb2srv_request *req; + uint32_t chain_offset; + uint32_t protocol_version; + uint16_t buffer_code; + uint32_t dynamic_size; + + chain_offset = p_req->chain_offset; + p_req->chain_offset = 0; + + if (p_req->in.size < (NBT_HDR_SIZE + chain_offset + SMB2_MIN_SIZE)) { + DEBUG(2,("Invalid SMB2 chained packet at offset 0x%X\n", + chain_offset)); + smbsrv_terminate_connection(p_req->smb_conn, "Invalid SMB2 chained packet"); + return; + } + + protocol_version = IVAL(p_req->in.buffer, NBT_HDR_SIZE + chain_offset); + if (protocol_version != SMB2_MAGIC) { + DEBUG(2,("Invalid SMB chained packet: protocol prefix: 0x%08X\n", + protocol_version)); + smbsrv_terminate_connection(p_req->smb_conn, "NON-SMB2 chained packet"); + return; + } + + req = smb2srv_init_request(p_req->smb_conn); + if (!req) { + smbsrv_terminate_connection(p_req->smb_conn, "SMB2 chained packet - no memory"); + return; + } + + req->in.buffer = talloc_steal(req, p_req->in.buffer); + req->in.size = p_req->in.size; + req->request_time = p_req->request_time; + req->in.allocated = req->in.size; + + req->in.hdr = req->in.buffer+ NBT_HDR_SIZE + chain_offset; + req->in.body = req->in.hdr + SMB2_HDR_BODY; + req->in.body_size = req->in.size - (NBT_HDR_SIZE+ chain_offset + SMB2_HDR_BODY); + req->in.dynamic = NULL; + + buffer_code = SVAL(req->in.body, 0); + req->in.body_fixed = (buffer_code & ~1); + dynamic_size = req->in.body_size - req->in.body_fixed; + + if (dynamic_size != 0 && (buffer_code & 1)) { + req->in.dynamic = req->in.body + req->in.body_fixed; + if (smb2_oob(&req->in, req->in.dynamic, dynamic_size)) { + DEBUG(1,("SMB2 chained request invalid dynamic size 0x%x\n", + dynamic_size)); + smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER); + return; + } + } + + if (p_req->chained_file_handle) { + memcpy(req->_chained_file_handle, + p_req->_chained_file_handle, + sizeof(req->_chained_file_handle)); + req->chained_file_handle = req->_chained_file_handle; + } + + /* + * TODO: - make sure the length field is 64 + * - make sure it's a request + */ + + status = smb2srv_reply(req); + if (!NT_STATUS_IS_OK(status)) { + smbsrv_terminate_connection(req->smb_conn, nt_errstr(status)); + talloc_free(req); + return; + } +} + void smb2srv_send_reply(struct smb2srv_request *req) { DATA_BLOB blob; @@ -140,6 +219,10 @@ void smb2srv_send_reply(struct smb2srv_request *req) if (!NT_STATUS_IS_OK(status)) { smbsrv_terminate_connection(req->smb_conn, nt_errstr(status)); } + if (req->chain_offset) { + smb2srv_chain_reply(req); + return; + } talloc_free(req); } @@ -174,10 +257,11 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) uint32_t tid; uint64_t uid; - opcode = SVAL(req->in.hdr, SMB2_HDR_OPCODE); - req->seqnum = BVAL(req->in.hdr, SMB2_HDR_SEQNUM); - tid = IVAL(req->in.hdr, SMB2_HDR_TID); - uid = BVAL(req->in.hdr, SMB2_HDR_UID); + opcode = SVAL(req->in.hdr, SMB2_HDR_OPCODE); + req->chain_offset = IVAL(req->in.hdr, SMB2_HDR_CHAIN_OFFSET); + req->seqnum = BVAL(req->in.hdr, SMB2_HDR_SEQNUM); + tid = IVAL(req->in.hdr, SMB2_HDR_TID); + uid = BVAL(req->in.hdr, SMB2_HDR_UID); req->session = smbsrv_session_find(req->smb_conn, uid, req->request_time); req->tcon = smbsrv_smb2_tcon_find(req->session, tid, req->request_time); @@ -311,7 +395,6 @@ NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob) } protocol_version = IVAL(blob.data, NBT_HDR_SIZE); - if (protocol_version != SMB2_MAGIC) { DEBUG(2,("Invalid SMB packet: protocol prefix: 0x%08X\n", protocol_version)); -- cgit From 6eaf8ee84960c85b703403a8c5ca440e330b0b80 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 21 May 2007 17:39:05 +0000 Subject: r23045: forward SMB2 oplock breaks to the client metze (This used to be commit 577acc198b096a1e182568b6db93c2da132b647e) --- source4/smb_server/smb2/receive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index bae3486014..98f2c3eeab 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -44,7 +44,7 @@ static int smb2srv_request_deny_destructor(struct smb2srv_request *req) return -1; } -static struct smb2srv_request *smb2srv_init_request(struct smbsrv_connection *smb_conn) +struct smb2srv_request *smb2srv_init_request(struct smbsrv_connection *smb_conn) { struct smb2srv_request *req; -- cgit From 0479a2f1cbae51fcd8dbdc3c148c808421fb4d25 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 02:07:03 +0000 Subject: r23792: convert Samba4 to GPLv3 There are still a few tidyups of old FSF addresses to come (in both s3 and s4). More commits soon. (This used to be commit fcf38a38ac691abd0fa51b89dc951a08e89fdafa) --- source4/smb_server/smb2/receive.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 98f2c3eeab..a8c0e6f786 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -6,7 +6,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -15,8 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #include "includes.h" -- cgit From ffeee68e4b72dd94fee57366bd8d38b8c284c3d4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 8 Sep 2007 12:42:09 +0000 Subject: r25026: Move param/param.h out of includes.h (This used to be commit abe8349f9b4387961ff3665d8c589d61cd2edf31) --- source4/smb_server/smb2/receive.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index a8c0e6f786..6a36d2f365 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -28,6 +28,7 @@ #include "smbd/service_stream.h" #include "lib/stream/packet.h" #include "ntvfs/ntvfs.h" +#include "param/param.h" static int smb2srv_request_destructor(struct smb2srv_request *req) { -- cgit From 98b57d5eb61094a9c88e2f7d90d3e21b7e74e9d8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 8 Sep 2007 16:46:30 +0000 Subject: r25035: Fix some more warnings, use service pointer rather than service number in more places. (This used to be commit df9cebcb97e20564359097148665bd519f31bc6f) --- source4/smb_server/smb2/receive.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 6a36d2f365..e783620e52 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -82,7 +82,8 @@ NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_si req->out.size = SMB2_HDR_BODY+NBT_HDR_SIZE+body_fixed_size; req->out.allocated = req->out.size + body_dynamic_size; - req->out.buffer = talloc_size(req, req->out.allocated); + req->out.buffer = talloc_array(req, uint8_t, + req->out.allocated); NT_STATUS_HAVE_NO_MEMORY(req->out.buffer); req->out.hdr = req->out.buffer + NBT_HDR_SIZE; -- cgit From 37d53832a4623653f706e77985a79d84bd7c6694 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 28 Sep 2007 01:17:46 +0000 Subject: r25398: Parse loadparm context to all lp_*() functions. (This used to be commit 3fcc960839c6e5ca4de2c3c042f12f369ac5f238) --- source4/smb_server/smb2/receive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index e783620e52..31b7f72cca 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -516,7 +516,7 @@ NTSTATUS smbsrv_init_smb2_connection(struct smbsrv_connection *smb_conn) /* this is the size that w2k uses, and it appears to be important for good performance */ - smb_conn->negotiate.max_recv = lp_max_xmit(); + smb_conn->negotiate.max_recv = lp_max_xmit(global_loadparm); smb_conn->negotiate.zone_offset = get_time_zone(time(NULL)); -- cgit From 0c56f8dac31c51a42dedf2a1da9fd76896855b19 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 6 Oct 2007 22:10:49 +0000 Subject: r25551: Convert to standard bool type. (This used to be commit c9651e2c5c078edee7b91085e936a93625c8d708) --- source4/smb_server/smb2/receive.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 31b7f72cca..a440c33dc0 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -59,7 +59,7 @@ struct smb2srv_request *smb2srv_init_request(struct smbsrv_connection *smb_conn) } NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_size, - BOOL body_dynamic_present, uint32_t body_dynamic_size) + bool body_dynamic_present, uint32_t body_dynamic_size) { uint32_t flags = 0x00000001; uint32_t pid = IVAL(req->in.hdr, SMB2_HDR_PID); @@ -237,7 +237,7 @@ void smb2srv_send_error(struct smb2srv_request *req, NTSTATUS error) return; } - status = smb2srv_setup_reply(req, 8, True, 0); + status = smb2srv_setup_reply(req, 8, true, 0); if (!NT_STATUS_IS_OK(status)) { smbsrv_terminate_connection(req->smb_conn, nt_errstr(status)); talloc_free(req); @@ -521,7 +521,7 @@ NTSTATUS smbsrv_init_smb2_connection(struct smbsrv_connection *smb_conn) smb_conn->negotiate.zone_offset = get_time_zone(time(NULL)); smb_conn->config.security = SEC_USER; - smb_conn->config.nt_status_support = True; + smb_conn->config.nt_status_support = true; status = smbsrv_init_sessions(smb_conn, UINT64_MAX); NT_STATUS_NOT_OK_RETURN(status); -- cgit From b83a7a135f3247f553cb04173646b2d871b97235 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 3 Dec 2007 21:25:17 +0100 Subject: r26268: Avoid more use of global_loadparm - put lp_ctx in smb_server and wbsrv_connection. (This used to be commit 7c008664238ed966cb82adf5b25b22157bb50730) --- source4/smb_server/smb2/receive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index a440c33dc0..cfae2dbe52 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -516,7 +516,7 @@ NTSTATUS smbsrv_init_smb2_connection(struct smbsrv_connection *smb_conn) /* this is the size that w2k uses, and it appears to be important for good performance */ - smb_conn->negotiate.max_recv = lp_max_xmit(global_loadparm); + smb_conn->negotiate.max_recv = lp_max_xmit(smb_conn->lp_ctx); smb_conn->negotiate.zone_offset = get_time_zone(time(NULL)); -- cgit From a2505c5a2cc2b7b692ffbcdd8c6b86000a15d2c7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Feb 2008 17:00:35 +1100 Subject: updated SMB2 header defines to match WSPP docs (This used to be commit d2c6ad55eca27f50a38fc6e2a85032eddb3f0aae) --- source4/smb_server/smb2/receive.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index cfae2dbe52..393b3f0cc5 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -94,17 +94,17 @@ NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_si SIVAL(req->out.hdr, 0, SMB2_MAGIC); SSVAL(req->out.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY); - SSVAL(req->out.hdr, SMB2_HDR_PAD1, 0); + SSVAL(req->out.hdr, SMB2_HDR_EPOCH, 0); SIVAL(req->out.hdr, SMB2_HDR_STATUS, NT_STATUS_V(req->status)); SSVAL(req->out.hdr, SMB2_HDR_OPCODE, SVAL(req->in.hdr, SMB2_HDR_OPCODE)); - SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1, 0x0001); + SSVAL(req->out.hdr, SMB2_HDR_CREDIT, 0x0001); SIVAL(req->out.hdr, SMB2_HDR_FLAGS, flags); - SIVAL(req->out.hdr, SMB2_HDR_CHAIN_OFFSET, 0); - SBVAL(req->out.hdr, SMB2_HDR_SEQNUM, req->seqnum); + SIVAL(req->out.hdr, SMB2_HDR_NEXT_COMMAND, 0); + SBVAL(req->out.hdr, SMB2_HDR_MESSAGE_ID, req->seqnum); SIVAL(req->out.hdr, SMB2_HDR_PID, pid); SIVAL(req->out.hdr, SMB2_HDR_TID, tid); - SBVAL(req->out.hdr, SMB2_HDR_UID, BVAL(req->in.hdr, SMB2_HDR_UID)); - memset(req->out.hdr+SMB2_HDR_SIG, 0, 16); + SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, BVAL(req->in.hdr, SMB2_HDR_SESSION_ID)); + memset(req->out.hdr+SMB2_HDR_SIGNATURE, 0, 16); /* set the length of the fixed body part and +1 if there's a dynamic part also */ SSVAL(req->out.body, 0, body_fixed_size + (body_dynamic_size?1:0)); @@ -259,10 +259,10 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) uint64_t uid; opcode = SVAL(req->in.hdr, SMB2_HDR_OPCODE); - req->chain_offset = IVAL(req->in.hdr, SMB2_HDR_CHAIN_OFFSET); - req->seqnum = BVAL(req->in.hdr, SMB2_HDR_SEQNUM); + req->chain_offset = IVAL(req->in.hdr, SMB2_HDR_NEXT_COMMAND); + req->seqnum = BVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID); tid = IVAL(req->in.hdr, SMB2_HDR_TID); - uid = BVAL(req->in.hdr, SMB2_HDR_UID); + uid = BVAL(req->in.hdr, SMB2_HDR_SESSION_ID); req->session = smbsrv_session_find(req->smb_conn, uid, req->request_time); req->tcon = smbsrv_smb2_tcon_find(req->session, tid, req->request_time); -- cgit From e870cfec9f3512b0f1bd3110d7b975652525e28a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Feb 2008 10:12:33 +1100 Subject: Convert SMB and SMB2 code to use a common buffer handling structure This converts our SMB and SMB2 code to use a common structure "struct request_bufinfo" for information on the buffer bounds of a packet, alignment information and string handling. This allows us to use a common backend for SMB and SMB2 code, while still using all the same string and blob handling functions. Up to now we had been passing a NULL req handle into these common routines from the SMB2 side of the server, which meant that we failed any operation which did a bounds checked string extraction (such as a RenameInformation setinfo call, which is what Vista uses for renaming files) There is still some more work to be done on this - for example we can now remove many of the SMB2 specific buffer handling functions that we had, and use the SMB ones. (This used to be commit ca6d9be6cb6a403a81b18fa6e9a6a0518d7f0f68) --- source4/smb_server/smb2/receive.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 393b3f0cc5..58070065fc 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -30,6 +30,22 @@ #include "ntvfs/ntvfs.h" #include "param/param.h" + +/* fill in the bufinfo */ +void smb2srv_setup_bufinfo(struct smb2srv_request *req) +{ + req->in.bufinfo.mem_ctx = req; + req->in.bufinfo.unicode = true; + req->in.bufinfo.align_base = req->in.buffer; + if (req->in.dynamic) { + req->in.bufinfo.data = req->in.dynamic; + req->in.bufinfo.data_size = req->in.body_size - req->in.body_fixed; + } else { + req->in.bufinfo.data = NULL; + req->in.bufinfo.data_size = 0; + } +} + static int smb2srv_request_destructor(struct smb2srv_request *req) { DLIST_REMOVE(req->smb_conn->requests2.list, req); @@ -180,6 +196,8 @@ static void smb2srv_chain_reply(struct smb2srv_request *p_req) } } + smb2srv_setup_bufinfo(req); + if (p_req->chained_file_handle) { memcpy(req->_chained_file_handle, p_req->_chained_file_handle, @@ -430,6 +448,8 @@ NTSTATUS smbsrv_recv_smb2_request(void *private, DATA_BLOB blob) } } + smb2srv_setup_bufinfo(req); + /* * TODO: - make sure the length field is 64 * - make sure it's a request -- cgit From 839ab724dc2d204bfbb0693aeed64f6f83a4266b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 14 Feb 2008 12:30:31 +1100 Subject: Fixed SMB2 rename operations from Vista clients We needed a flag in bufinfo to mark packets as SMB2, as it seems that SMB2 uses a different format for the RenameInformation buffer than SMB does Also handle the fact that SMB2 clients give the full path to the target file in the rename, not a relative path (This used to be commit 52d7972d95ddc19d22a4187b4d4428a6c3ed32d5) --- source4/smb_server/smb2/receive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 58070065fc..dea7c9e79e 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -35,7 +35,7 @@ void smb2srv_setup_bufinfo(struct smb2srv_request *req) { req->in.bufinfo.mem_ctx = req; - req->in.bufinfo.unicode = true; + req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE | BUFINFO_FLAG_SMB2; req->in.bufinfo.align_base = req->in.buffer; if (req->in.dynamic) { req->in.bufinfo.data = req->in.dynamic; -- cgit From e97cf207fac5e4101376d2a10dd95a93a9a1e0fb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 6 Jun 2008 22:10:30 -0700 Subject: added server side SMB2 signing (This used to be commit 8e919dcb0826a5b25d037ee6144af5f7cb21f3ae) --- source4/smb_server/smb2/receive.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index dea7c9e79e..3def8fe563 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -29,6 +29,8 @@ #include "lib/stream/packet.h" #include "ntvfs/ntvfs.h" #include "param/param.h" +#include "auth/gensec/gensec.h" +#include "auth/auth.h" /* fill in the bufinfo */ @@ -233,6 +235,20 @@ void smb2srv_send_reply(struct smb2srv_request *req) _smb2_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE); } + /* if the request was signed or doing_signing is true, then we + must sign the reply */ + if (req->session && + (req->smb_conn->doing_signing || + (IVAL(req->in.hdr, SMB2_HDR_FLAGS) & SMB2_HDR_FLAG_SIGNED))) { + status = smb2_sign_message(&req->out, + req->session->session_info->session_key); + if (!NT_STATUS_IS_OK(status)) { + smbsrv_terminate_connection(req->smb_conn, nt_errstr(status)); + return; + } + } + + blob = data_blob_const(req->out.buffer, req->out.size); status = packet_send(req->smb_conn->packet, blob); if (!NT_STATUS_IS_OK(status)) { @@ -275,18 +291,38 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) uint16_t opcode; uint32_t tid; uint64_t uid; + uint32_t flags; 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); tid = IVAL(req->in.hdr, SMB2_HDR_TID); uid = BVAL(req->in.hdr, SMB2_HDR_SESSION_ID); + flags = IVAL(req->in.hdr, SMB2_HDR_FLAGS); req->session = smbsrv_session_find(req->smb_conn, uid, req->request_time); req->tcon = smbsrv_smb2_tcon_find(req->session, tid, req->request_time); errno = 0; + /* supporting signing is mandatory in SMB2, and is per-packet. So we + should check the signature on any incoming packet that is signed, and + should give a signed reply to any signed request */ + if (flags & SMB2_HDR_FLAG_SIGNED) { + NTSTATUS status; + if (req->session == NULL) { + /* we can't check signing with no session */ + smb2srv_send_error(req, NT_STATUS_ACCESS_DENIED); + return NT_STATUS_OK; + } + status = smb2_check_signature(&req->in, + req->session->session_info->session_key); + if (!NT_STATUS_IS_OK(status)) { + smb2srv_send_error(req, status); + return NT_STATUS_OK; + } + } + /* TODO: check the seqnum */ switch (opcode) { -- cgit From e4ad580b99c5b372353c285569204ab94c177748 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 7 Jun 2008 08:14:25 -0700 Subject: fixed mandatory signing Metze pointed out that if signing is mandatory in the server then we need to reject packets without the signed flag if the packet contains a session id. (This used to be commit 056f16e664e581bab1c07759e99ad4f6685c58eb) --- source4/smb_server/smb2/receive.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 3def8fe563..2f4e9df2b6 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -321,6 +321,10 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) smb2srv_send_error(req, status); return NT_STATUS_OK; } + } else if (req->smb_conn->doing_signing && req->session != NULL) { + /* we require signing and this request was not signed */ + smb2srv_send_error(req, NT_STATUS_ACCESS_DENIED); + return NT_STATUS_OK; } /* TODO: check the seqnum */ -- cgit From 8623e2cc4ca3b7fefcdc943c1da8a89b805f5d29 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 9 Jun 2008 21:45:19 +0200 Subject: smb2srv: correctly hold the signing state per session metze (This used to be commit 5b3ba3f3556e8031133128853cd2324ee3852aa1) --- source4/smb_server/smb2/receive.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 2f4e9df2b6..cfd6c1d01a 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -235,11 +235,8 @@ void smb2srv_send_reply(struct smb2srv_request *req) _smb2_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE); } - /* if the request was signed or doing_signing is true, then we - must sign the reply */ - if (req->session && - (req->smb_conn->doing_signing || - (IVAL(req->in.hdr, SMB2_HDR_FLAGS) & SMB2_HDR_FLAG_SIGNED))) { + /* if signing is active on the session then sign the packet */ + if (req->session && req->session->smb2_signing.active) { status = smb2_sign_message(&req->out, req->session->session_info->session_key); if (!NT_STATUS_IS_OK(status)) { @@ -310,18 +307,22 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) should give a signed reply to any signed request */ if (flags & SMB2_HDR_FLAG_SIGNED) { NTSTATUS status; - if (req->session == NULL) { - /* we can't check signing with no session */ - smb2srv_send_error(req, NT_STATUS_ACCESS_DENIED); - return NT_STATUS_OK; + + if (!req->session) goto nosession; + + if (!req->session->smb2_signing.active) { + /* TODO: workout the correct error code */ + smb2srv_send_error(req, NT_STATUS_FOOBAR); + return NT_STATUS_OK; } + status = smb2_check_signature(&req->in, req->session->session_info->session_key); if (!NT_STATUS_IS_OK(status)) { smb2srv_send_error(req, status); return NT_STATUS_OK; } - } else if (req->smb_conn->doing_signing && req->session != NULL) { + } else if (req->session && req->session->smb2_signing.active) { /* we require signing and this request was not signed */ smb2srv_send_error(req, NT_STATUS_ACCESS_DENIED); return NT_STATUS_OK; -- cgit From 4a214dba301474c48f2ae45194b0e363440ee01d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 13 Aug 2008 09:45:44 +0200 Subject: smb2srv: use defines instead of hex values metze (This used to be commit 7c4abf6614c47471ae005a12abe27d85890d867f) --- source4/smb_server/smb2/receive.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index cfd6c1d01a..007125c4c4 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -79,12 +79,12 @@ struct smb2srv_request *smb2srv_init_request(struct smbsrv_connection *smb_conn) NTSTATUS smb2srv_setup_reply(struct smb2srv_request *req, uint16_t body_fixed_size, bool body_dynamic_present, uint32_t body_dynamic_size) { - uint32_t flags = 0x00000001; + uint32_t flags = SMB2_HDR_FLAG_REDIRECT; uint32_t pid = IVAL(req->in.hdr, SMB2_HDR_PID); uint32_t tid = IVAL(req->in.hdr, SMB2_HDR_TID); if (req->pending_id) { - flags |= 0x00000002; + flags |= SMB2_HDR_FLAG_ASYNC; pid = req->pending_id; tid = 0; } @@ -545,7 +545,7 @@ void smb2srv_cancel_recv(struct smb2srv_request *req) flags = IVAL(req->in.hdr, SMB2_HDR_FLAGS); pending_id = IVAL(req->in.hdr, SMB2_HDR_PID); - if (!(flags & 0x00000002)) { + if (!(flags & SMB2_HDR_FLAG_ASYNC)) { /* TODO: what to do here? */ goto done; } -- cgit From 0294c678c0665e675673ff477df26fddd8ed53dd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 13 Aug 2008 15:20:18 +0200 Subject: smb2srv: sign replies when the request was also signed metze (This used to be commit dd2f4f7a491debcc30e590f571272afd99e52940) --- source4/smb_server/smb2/receive.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index 007125c4c4..bcc91e4ee3 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -236,7 +236,7 @@ void smb2srv_send_reply(struct smb2srv_request *req) } /* if signing is active on the session then sign the packet */ - if (req->session && req->session->smb2_signing.active) { + if (req->is_signed) { status = smb2_sign_message(&req->out, req->session->session_info->session_key); if (!NT_STATUS_IS_OK(status)) { @@ -310,12 +310,7 @@ static NTSTATUS smb2srv_reply(struct smb2srv_request *req) if (!req->session) goto nosession; - if (!req->session->smb2_signing.active) { - /* TODO: workout the correct error code */ - smb2srv_send_error(req, NT_STATUS_FOOBAR); - return NT_STATUS_OK; - } - + req->is_signed = true; status = smb2_check_signature(&req->in, req->session->session_info->session_key); if (!NT_STATUS_IS_OK(status)) { -- cgit From 2a36568129877273f6c559bd5c3bdb8f2efef8c7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 13 Aug 2008 09:48:44 +0200 Subject: smb2srv: async replies with STATUS_PENDING are not signed ..., but the they may have the sign flag set. metze (This used to be commit 43e43dead030f6bffd06631007fdb162c3c6b2b5) --- source4/smb_server/smb2/receive.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'source4/smb_server/smb2/receive.c') diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c index bcc91e4ee3..1fe6f0b877 100644 --- a/source4/smb_server/smb2/receive.c +++ b/source4/smb_server/smb2/receive.c @@ -506,6 +506,8 @@ static NTSTATUS smb2srv_init_pending(struct smbsrv_connection *smb_conn) NTSTATUS smb2srv_queue_pending(struct smb2srv_request *req) { + NTSTATUS status; + bool signing_used = false; int id; if (req->pending_id) { @@ -521,10 +523,35 @@ NTSTATUS smb2srv_queue_pending(struct smb2srv_request *req) DLIST_ADD_END(req->smb_conn->requests2.list, req, struct smb2srv_request *); req->pending_id = id; + if (req->smb_conn->connection->event.fde == NULL) { + /* the socket has been destroyed - no point trying to send an error! */ + return NT_STATUS_REMOTE_DISCONNECT; + } + talloc_set_destructor(req, smb2srv_request_deny_destructor); - smb2srv_send_error(req, STATUS_PENDING); - talloc_set_destructor(req, smb2srv_request_destructor); + status = smb2srv_setup_reply(req, 8, true, 0); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + SIVAL(req->out.hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING)); + + SSVAL(req->out.body, 0x02, 0); + SIVAL(req->out.body, 0x04, 0); + + /* if the real reply will be signed set the signed flags, but don't sign */ + if (req->is_signed) { + SIVAL(req->out.hdr, SMB2_HDR_FLAGS, IVAL(req->out.hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED); + signing_used = req->is_signed; + req->is_signed = false; + } + + smb2srv_send_reply(req); + + req->is_signed = signing_used; + + talloc_set_destructor(req, smb2srv_request_destructor); return NT_STATUS_OK; } -- cgit