[SCM] Samba Shared Repository - branch master updated -
release-4-0-0alpha7-1719-g4abd5f3
Stefan Metzmacher
metze at samba.org
Wed May 20 13:43:38 GMT 2009
The branch, master has been updated
via 4abd5f34d97d759afd92ca854d9fffb382a4f999 (commit)
via d7d73b08e993f6ca5948c3bbe653352573c6f43d (commit)
via 3ef6a5ae9ebefb18755337a83ba5488e8b8edd6e (commit)
via c14dd15c6a802729f46857630b1df83987d9a11c (commit)
via 688945a994660fa905836b55a995bb90c3e8e67a (commit)
via d23a1935e8180090474cbbba878d5bc5903579c6 (commit)
from d59f84d738401f3ab8ec34aa053af05670a58a89 (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 4abd5f34d97d759afd92ca854d9fffb382a4f999
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri May 15 12:07:28 2009 +0200
s3:smbd: add support for SMB2 Keepalive (SMB2 Echo)
metze
commit d7d73b08e993f6ca5948c3bbe653352573c6f43d
Author: Stefan Metzmacher <metze at samba.org>
Date: Tue May 19 10:47:51 2009 +0200
s3:smbd: allow SMB 2.002 dialect in SMB1 negprot
We create a dummy SMB2 Negotiate inbuf and pass the
connection to the SMB2 engine.
metze
commit 3ef6a5ae9ebefb18755337a83ba5488e8b8edd6e
Author: Stefan Metzmacher <metze at samba.org>
Date: Thu May 14 15:32:02 2009 +0200
s3:smbd: add support for SMB2 Negotiate
This is not complete, but a start that makes the
samba4 smb2 client happy.
metze
commit c14dd15c6a802729f46857630b1df83987d9a11c
Author: Stefan Metzmacher <metze at samba.org>
Date: Tue May 19 10:46:35 2009 +0200
s3:smbd: make negprot_spnego() non static
metze
commit 688945a994660fa905836b55a995bb90c3e8e67a
Author: Stefan Metzmacher <metze at samba.org>
Date: Thu May 14 14:17:28 2009 +0200
s3:smbd: add infrastructure for SMB2 support
This is disabled by default and activated by
"max protocol = SMB2".
metze
commit d23a1935e8180090474cbbba878d5bc5903579c6
Author: Stefan Metzmacher <metze at samba.org>
Date: Tue May 19 10:45:38 2009 +0200
s3:param: add PROTOCOL_SMB2
metze
-----------------------------------------------------------------------
Summary of changes:
source3/Makefile.in | 2 +
source3/include/smb.h | 10 +-
source3/param/loadparm.c | 1 +
source3/smbd/globals.h | 82 ++++
source3/smbd/negprot.c | 3 +-
source3/smbd/process.c | 12 +
source3/smbd/smb2_keepalive.c | 55 +++
source3/smbd/smb2_negprot.c | 163 +++++++
source3/smbd/smb2_server.c | 999 +++++++++++++++++++++++++++++++++++++++++
9 files changed, 1325 insertions(+), 2 deletions(-)
create mode 100644 source3/smbd/smb2_keepalive.c
create mode 100644 source3/smbd/smb2_negprot.c
create mode 100644 source3/smbd/smb2_server.c
Changeset truncated at 500 lines:
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 31ef29a..f5074e3 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -748,6 +748,8 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/dmapi.o smbd/signing.o \
smbd/file_access.o \
smbd/dnsregister.o smbd/globals.o \
+ smbd/smb2_server.o smbd/smb2_negprot.o \
+ smbd/smb2_keepalive.o \
$(MANGLE_OBJ) @VFS_STATIC@
SMBD_OBJ_BASE = $(PARAM_WITHOUT_REG_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \
diff --git a/source3/include/smb.h b/source3/include/smb.h
index fed7468..abcd494 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -1518,7 +1518,15 @@ char *strdup(char *s);
/* protocol types. It assumes that higher protocols include lower protocols
as subsets */
-enum protocol_types {PROTOCOL_NONE,PROTOCOL_CORE,PROTOCOL_COREPLUS,PROTOCOL_LANMAN1,PROTOCOL_LANMAN2,PROTOCOL_NT1};
+enum protocol_types {
+ PROTOCOL_NONE,
+ PROTOCOL_CORE,
+ PROTOCOL_COREPLUS,
+ PROTOCOL_LANMAN1,
+ PROTOCOL_LANMAN2,
+ PROTOCOL_NT1,
+ PROTOCOL_SMB2
+};
/* security levels */
enum security_types {SEC_SHARE,SEC_USER,SEC_SERVER,SEC_DOMAIN,SEC_ADS};
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index da3da63..6da792a 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -685,6 +685,7 @@ static void *lp_local_ptr(struct service *service, void *ptr);
static void add_to_file_list(const char *fname, const char *subfname);
static const struct enum_list enum_protocol[] = {
+ {PROTOCOL_SMB2, "SMB2"},
{PROTOCOL_NT1, "NT1"},
{PROTOCOL_LANMAN2, "LANMAN2"},
{PROTOCOL_LANMAN1, "LANMAN1"},
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index b646bc3..c5dd97c 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -199,11 +199,93 @@ struct child_pid;
extern struct child_pid *children;
extern int num_children;
+struct tstream_context;
+struct smbd_smb2_request;
+
+DATA_BLOB negprot_spnego(void);
+
+bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size);
+
+void reply_smb2002(struct smb_request *req, uint16_t choice);
+void smbd_smb2_first_negprot(struct smbd_server_connection *conn,
+ const uint8_t *inbuf, size_t size);
+
+NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
+ NTSTATUS status, DATA_BLOB *info);
+NTSTATUS smbd_smb2_request_error(struct smbd_smb2_request *req,
+ NTSTATUS status);
+NTSTATUS smbd_smb2_request_done(struct smbd_smb2_request *req,
+ DATA_BLOB body, DATA_BLOB *dyn);
+
+NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req);
+NTSTATUS smbd_smb2_request_process_keepalive(struct smbd_smb2_request *req);
+
+struct smbd_smb2_request {
+ TALLOC_CTX *mem_pool;
+
+ struct smbd_server_connection *conn;
+
+ int current_idx;
+
+ struct {
+ /* the NBT header is not allocated */
+ uint8_t nbt_hdr[4];
+ /*
+ * vector[0] NBT
+ * .
+ * vector[1] SMB2
+ * vector[2] fixed body
+ * vector[3] dynamic body
+ * .
+ * .
+ * .
+ * vector[4] SMB2
+ * vector[5] fixed body
+ * vector[6] dynamic body
+ * .
+ * .
+ * .
+ */
+ struct iovec *vector;
+ int vector_count;
+ } in;
+ struct {
+ /* the NBT header is not allocated */
+ uint8_t nbt_hdr[4];
+ /*
+ * vector[0] NBT
+ * .
+ * vector[1] SMB2
+ * vector[2] fixed body
+ * vector[3] dynamic body
+ * .
+ * .
+ * .
+ * vector[4] SMB2
+ * vector[5] fixed body
+ * vector[6] dynamic body
+ * .
+ * .
+ * .
+ */
+ struct iovec *vector;
+ int vector_count;
+ } out;
+};
+
struct smbd_server_connection {
struct fd_event *fde;
uint64_t num_requests;
struct smb_signing_state *signing_state;
+ bool allow_smb2;
+ struct {
+ struct tevent_context *event_ctx;
+ struct tevent_queue *recv_queue;
+ struct tevent_queue *send_queue;
+ struct tstream_context *stream;
+ } smb2;
};
+
extern struct smbd_server_connection *smbd_server_conn;
void smbd_init_globals(void);
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index e548c58..6d15f48 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -166,7 +166,7 @@ static void reply_lanman2(struct smb_request *req, uint16 choice)
Generate the spnego negprot reply blob. Return the number of bytes used.
****************************************************************************/
-static DATA_BLOB negprot_spnego(void)
+DATA_BLOB negprot_spnego(void)
{
DATA_BLOB blob;
nstring dos_name;
@@ -481,6 +481,7 @@ static const struct {
void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
int protocol_level;
} supported_protocols[] = {
+ {"SMB 2.002", "SMB2", reply_smb2002, PROTOCOL_SMB2},
{"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
{"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
{"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1},
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 0647b99..5cad8bf 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -1448,6 +1448,14 @@ static void process_smb(struct smbd_server_connection *conn,
goto done;
}
+ if (smbd_server_conn->allow_smb2) {
+ if (smbd_is_smb2_header(inbuf, nread)) {
+ smbd_smb2_first_negprot(smbd_server_conn, inbuf, nread);
+ return;
+ }
+ smbd_server_conn->allow_smb2 = false;
+ }
+
show_msg((char *)inbuf);
construct_reply((char *)inbuf,nread,unread_bytes,seqnum,encrypted,deferred_pcd);
@@ -2009,6 +2017,10 @@ void smbd_process(void)
exit_server("failed to create smbd_server_connection");
}
+ if (lp_maxprotocol() == PROTOCOL_SMB2) {
+ smbd_server_conn->allow_smb2 = true;
+ }
+
/* Ensure child is set to blocking mode */
set_blocking(smbd_server_fd(),True);
diff --git a/source3/smbd/smb2_keepalive.c b/source3/smbd/smb2_keepalive.c
new file mode 100644
index 0000000..0028fd3
--- /dev/null
+++ b/source3/smbd/smb2_keepalive.c
@@ -0,0 +1,55 @@
+/*
+ Unix SMB/CIFS implementation.
+ Core SMB2 server
+
+ Copyright (C) Stefan Metzmacher 2009
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "smbd/globals.h"
+#include "../source4/libcli/smb2/smb2_constants.h"
+
+NTSTATUS smbd_smb2_request_process_keepalive(struct smbd_smb2_request *req)
+{
+ const uint8_t *inbody;
+ int i = req->current_idx;
+ DATA_BLOB outbody;
+ size_t expected_body_size = 0x04;
+ size_t body_size;
+
+ if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
+ return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+ }
+
+ inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
+
+ body_size = SVAL(inbody, 0x00);
+ if (body_size != expected_body_size) {
+ return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+ }
+
+ /* TODO: update some time stamps */
+
+ outbody = data_blob_talloc(req->out.vector, NULL, 0x04);
+ if (outbody.data == NULL) {
+ return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
+ }
+
+ SSVAL(outbody.data, 0x00, 0x04); /* struct size */
+ SSVAL(outbody.data, 0x02, 0); /* reserved */
+
+ return smbd_smb2_request_done(req, outbody, NULL);
+}
diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c
new file mode 100644
index 0000000..38dfe6d
--- /dev/null
+++ b/source3/smbd/smb2_negprot.c
@@ -0,0 +1,163 @@
+/*
+ Unix SMB/CIFS implementation.
+ Core SMB2 server
+
+ Copyright (C) Stefan Metzmacher 2009
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "smbd/globals.h"
+#include "../source4/libcli/smb2/smb2_constants.h"
+
+extern enum protocol_types Protocol;
+
+/*
+ * this is the entry point if SMB2 is selected via
+ * the SMB negprot
+ */
+void reply_smb2002(struct smb_request *req, uint16_t choice)
+{
+ uint8_t *smb2_inbuf;
+ uint8_t *smb2_hdr;
+ uint8_t *smb2_body;
+ uint8_t *smb2_dyn;
+ size_t len = 4 + SMB2_HDR_BODY + 0x24 + 2;
+
+ smb2_inbuf = talloc_zero_array(talloc_tos(), uint8_t, len);
+ if (smb2_inbuf == NULL) {
+ DEBUG(0, ("Could not push spnego blob\n"));
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+ smb2_hdr = smb2_inbuf + 4;
+ smb2_body = smb2_hdr + SMB2_HDR_BODY;
+ smb2_dyn = smb2_body + 0x24;
+
+ SIVAL(smb2_hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
+ SIVAL(smb2_hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
+
+ SSVAL(smb2_body, 0x00, 0x0024); /* struct size */
+ SSVAL(smb2_body, 0x02, 0x0001); /* dialect count */
+
+ SSVAL(smb2_dyn, 0x00, 0x0202); /* dialect 2.002 */
+
+ req->outbuf = NULL;
+
+ smbd_smb2_first_negprot(smbd_server_conn, smb2_inbuf, len);
+ return;
+}
+
+NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
+{
+ const uint8_t *inbody;
+ const uint8_t *indyn = NULL;
+ int i = req->current_idx;
+ DATA_BLOB outbody;
+ DATA_BLOB outdyn;
+ DATA_BLOB negprot_spnego_blob;
+ uint16_t security_offset;
+ DATA_BLOB security_buffer;
+ size_t expected_body_size = 0x24;
+ size_t body_size;
+ size_t expected_dyn_size = 0;
+ size_t c;
+ uint16_t dialect_count;
+ uint16_t dialect;
+
+/* TODO: drop the connection with INVALI_PARAMETER */
+
+ if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
+ return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+ }
+
+ inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
+
+ body_size = SVAL(inbody, 0x00);
+ if (body_size != expected_body_size) {
+ return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+ }
+
+ dialect_count = SVAL(inbody, 0x02);
+ if (dialect_count == 0) {
+ return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+ }
+
+ expected_dyn_size = dialect_count * 2;
+ if (req->in.vector[i+2].iov_len < expected_dyn_size) {
+ return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+ }
+ indyn = (const uint8_t *)req->in.vector[i+2].iov_base;
+
+ for (c=0; c < dialect_count; c++) {
+ dialect = SVAL(indyn, c*2);
+ if (dialect == 0x0202) {
+ break;
+ }
+ }
+
+ if (dialect != 0x0202) {
+ return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+ }
+
+ Protocol = PROTOCOL_SMB2;
+
+ if (get_remote_arch() != RA_SAMBA) {
+ set_remote_arch(RA_VISTA);
+ }
+
+ /* negprot_spnego() returns a the server guid in the first 16 bytes */
+ negprot_spnego_blob = negprot_spnego();
+ if (negprot_spnego_blob.data == NULL) {
+ return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
+ }
+ talloc_steal(req, negprot_spnego_blob.data);
+
+ if (negprot_spnego_blob.length < 16) {
+ return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
+ }
+
+ security_offset = SMB2_HDR_BODY + 0x40;
+ security_buffer = data_blob_const(negprot_spnego_blob.data + 16,
+ negprot_spnego_blob.length - 16);
+
+ outbody = data_blob_talloc(req->out.vector, NULL, 0x40);
+ if (outbody.data == NULL) {
+ return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
+ }
+
+ SSVAL(outbody.data, 0x00, 0x40 + 1); /* struct size */
+/*TODO: indicate signing enabled */
+ SSVAL(outbody.data, 0x02, 0); /* security mode */
+ SSVAL(outbody.data, 0x04, dialect); /* dialect revision */
+ SSVAL(outbody.data, 0x06, 0); /* reserved */
+ memcpy(outbody.data + 0x08,
+ negprot_spnego_blob.data, 16); /* server guid */
+ SIVAL(outbody.data, 0x18, 0); /* capabilities */
+ SIVAL(outbody.data, 0x1C, 0x00010000); /* max transact size */
+ SIVAL(outbody.data, 0x20, 0x00010000); /* max read size */
+ SIVAL(outbody.data, 0x24, 0x00010000); /* max write size */
+ SBVAL(outbody.data, 0x28, 0); /* system time */
+ SBVAL(outbody.data, 0x30, 0); /* server start time */
+ SSVAL(outbody.data, 0x38,
+ security_offset); /* security buffer offset */
+ SSVAL(outbody.data, 0x3A,
+ security_buffer.length); /* security buffer length */
+ SIVAL(outbody.data, 0x3C, 0); /* reserved */
+
+ outdyn = security_buffer;
+
+ return smbd_smb2_request_done(req, outbody, &outdyn);
+}
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
new file mode 100644
index 0000000..9be6a73
--- /dev/null
+++ b/source3/smbd/smb2_server.c
@@ -0,0 +1,999 @@
+/*
+ Unix SMB/CIFS implementation.
+ Core SMB2 server
+
+ Copyright (C) Stefan Metzmacher 2009
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "smbd/globals.h"
+#include "../source4/libcli/smb2/smb2_constants.h"
+#include "../lib/tsocket/tsocket.h"
+
+bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
+{
+ if (size < (4 + SMB2_HDR_BODY)) {
+ return false;
+ }
+
+ if (IVAL(inbuf, 4) != SMB2_MAGIC) {
+ return false;
+ }
+
+ return true;
+}
+
+static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *conn)
+{
+ NTSTATUS status;
+ int ret;
+
+ TALLOC_FREE(conn->fde);
+
+ conn->smb2.event_ctx = smbd_event_context();
+
+ conn->smb2.recv_queue = tevent_queue_create(conn, "smb2 recv queue");
+ if (conn->smb2.recv_queue == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ conn->smb2.send_queue = tevent_queue_create(conn, "smb2 send queue");
+ if (conn->smb2.send_queue == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = tstream_bsd_existing_socket(conn, smbd_server_fd(),
+ &conn->smb2.stream);
+ if (ret == -1) {
+ status = map_nt_error_from_unix(errno);
+ return status;
+ }
+
+ /* Ensure child is set to non-blocking mode */
+ set_blocking(smbd_server_fd(),false);
+ return NT_STATUS_OK;
+}
+
--
Samba Shared Repository
More information about the samba-cvs
mailing list