summaryrefslogtreecommitdiff
path: root/source4/smb_server/smb2
diff options
context:
space:
mode:
Diffstat (limited to 'source4/smb_server/smb2')
-rw-r--r--source4/smb_server/smb2/config.mk1
-rw-r--r--source4/smb_server/smb2/fileinfo.c49
-rw-r--r--source4/smb_server/smb2/fileio.c27
-rw-r--r--source4/smb_server/smb2/find.c5
-rw-r--r--source4/smb_server/smb2/negprot.c104
-rw-r--r--source4/smb_server/smb2/receive.c38
-rw-r--r--source4/smb_server/smb2/sesssetup.c27
-rw-r--r--source4/smb_server/smb2/tcon.c57
8 files changed, 189 insertions, 119 deletions
diff --git a/source4/smb_server/smb2/config.mk b/source4/smb_server/smb2/config.mk
index b878d404c8..d5ba43b3a8 100644
--- a/source4/smb_server/smb2/config.mk
+++ b/source4/smb_server/smb2/config.mk
@@ -13,6 +13,5 @@ OBJ_FILES = \
keepalive.o
PUBLIC_DEPENDENCIES = \
ntvfs LIBPACKET LIBCLI_SMB2
-LDFLAGS = $(SUBSYSTEM_SMB_SERVER_OUTPUT)
# End SUBSYSTEM SMB2_PROTOCOL
#######################
diff --git a/source4/smb_server/smb2/fileinfo.c b/source4/smb_server/smb2/fileinfo.c
index 00c455e351..d6db61eaba 100644
--- a/source4/smb_server/smb2/fileinfo.c
+++ b/source4/smb_server/smb2/fileinfo.c
@@ -79,19 +79,21 @@ static NTSTATUS smb2srv_getinfo_file_send(struct smb2srv_getinfo_op *op)
static NTSTATUS smb2srv_getinfo_file(struct smb2srv_getinfo_op *op, uint8_t smb2_level)
{
union smb_fileinfo *io;
+ uint16_t level;
io = talloc(op, union smb_fileinfo);
NT_STATUS_HAVE_NO_MEMORY(io);
- switch (op->info->in.level) {
+ level = op->info->in.info_type | (op->info->in.info_class << 8);
+ switch (level) {
case RAW_FILEINFO_SMB2_ALL_EAS:
- io->all_eas.level = op->info->in.level;
+ io->all_eas.level = level;
io->all_eas.in.file.ntvfs = op->info->in.file.ntvfs;
- io->all_eas.in.continue_flags = op->info->in.flags2;
+ io->all_eas.in.continue_flags = op->info->in.getinfo_flags;
break;
case RAW_FILEINFO_SMB2_ALL_INFORMATION:
- io->all_info2.level = op->info->in.level;
+ io->all_info2.level = level;
io->all_info2.in.file.ntvfs = op->info->in.file.ntvfs;
break;
@@ -166,7 +168,7 @@ static NTSTATUS smb2srv_getinfo_security(struct smb2srv_getinfo_op *op, uint8_t
io->query_secdesc.level = RAW_FILEINFO_SEC_DESC;
io->query_secdesc.in.file.ntvfs = op->info->in.file.ntvfs;
- io->query_secdesc.in.secinfo_flags = op->info->in.flags;
+ io->query_secdesc.in.secinfo_flags = op->info->in.additional_information;
op->io_ptr = io;
op->send_fn = smb2srv_getinfo_security_send;
@@ -179,23 +181,17 @@ static NTSTATUS smb2srv_getinfo_security(struct smb2srv_getinfo_op *op, uint8_t
static NTSTATUS smb2srv_getinfo_backend(struct smb2srv_getinfo_op *op)
{
- uint8_t smb2_class;
- uint8_t smb2_level;
-
- smb2_class = 0xFF & op->info->in.level;
- smb2_level = 0xFF & (op->info->in.level>>8);
-
- switch (smb2_class) {
+ switch (op->info->in.info_type) {
case SMB2_GETINFO_FILE:
- return smb2srv_getinfo_file(op, smb2_level);
+ return smb2srv_getinfo_file(op, op->info->in.info_class);
case SMB2_GETINFO_FS:
- return smb2srv_getinfo_fs(op, smb2_level);
+ return smb2srv_getinfo_fs(op, op->info->in.info_class);
case SMB2_GETINFO_SECURITY:
- return smb2srv_getinfo_security(op, smb2_level);
+ return smb2srv_getinfo_security(op, op->info->in.info_class);
- case 0x04:
+ case SMB2_GETINFO_QUOTA:
return NT_STATUS_NOT_SUPPORTED;
}
@@ -217,13 +213,15 @@ void smb2srv_getinfo_recv(struct smb2srv_request *req)
op->send_fn = NULL;
SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_getinfo_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
- info->in.level = SVAL(req->in.body, 0x02);
- info->in.max_response_size = IVAL(req->in.body, 0x04);
- info->in.unknown1 = IVAL(req->in.body, 0x08);
- info->in.unknown2 = IVAL(req->in.body, 0x0C);
- info->in.flags = IVAL(req->in.body, 0x10);
- info->in.flags2 = IVAL(req->in.body, 0x14);
+ info->in.info_type = CVAL(req->in.body, 0x02);
+ info->in.info_class = CVAL(req->in.body, 0x03);
+ info->in.output_buffer_length = IVAL(req->in.body, 0x04);
+ info->in.reserved = IVAL(req->in.body, 0x0C);
+ info->in.additional_information = IVAL(req->in.body, 0x10);
+ info->in.getinfo_flags = IVAL(req->in.body, 0x14);
info->in.file.ntvfs = smb2srv_pull_handle(req, req->in.body, 0x18);
+ SMB2SRV_CHECK(smb2_pull_o16As32_blob(&req->in, op,
+ req->in.body+0x08, &info->in.blob));
SMB2SRV_CHECK_FILE_HANDLE(info->in.file.ntvfs);
SMB2SRV_CALL_NTVFS_BACKEND(smb2srv_getinfo_backend(op));
@@ -266,9 +264,14 @@ static NTSTATUS smb2srv_setinfo_file(struct smb2srv_setinfo_op *op, uint8_t smb2
io->generic.level = smb2_level + 1000;
io->generic.in.file.ntvfs = op->info->in.file.ntvfs;
+ /* handle cases that don't map directly */
+ if (io->generic.level == RAW_SFILEINFO_RENAME_INFORMATION) {
+ io->generic.level = RAW_SFILEINFO_RENAME_INFORMATION_SMB2;
+ }
+
status = smbsrv_pull_passthru_sfileinfo(io, io->generic.level, io,
&op->info->in.blob,
- STR_UNICODE, NULL);
+ STR_UNICODE, &op->req->in.bufinfo);
NT_STATUS_NOT_OK_RETURN(status);
return ntvfs_setfileinfo(op->req->ntvfs, io);
diff --git a/source4/smb_server/smb2/fileio.c b/source4/smb_server/smb2/fileio.c
index 0e83c78615..0e3df56b42 100644
--- a/source4/smb_server/smb2/fileio.c
+++ b/source4/smb_server/smb2/fileio.c
@@ -34,7 +34,8 @@ static void smb2srv_create_send(struct ntvfs_request *ntvfs)
SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_open);
SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x58, true, io->smb2.out.blob.length));
- SSVAL(req->out.body, 0x02, io->smb2.out.oplock_flags);
+ SCVAL(req->out.body, 0x02, io->smb2.out.oplock_level);
+ SCVAL(req->out.body, 0x03, io->smb2.out.reserved);
SIVAL(req->out.body, 0x04, io->smb2.out.create_action);
SBVAL(req->out.body, 0x08, io->smb2.out.create_time);
SBVAL(req->out.body, 0x10, io->smb2.out.access_time);
@@ -43,7 +44,7 @@ static void smb2srv_create_send(struct ntvfs_request *ntvfs)
SBVAL(req->out.body, 0x28, io->smb2.out.alloc_size);
SBVAL(req->out.body, 0x30, io->smb2.out.size);
SIVAL(req->out.body, 0x38, io->smb2.out.file_attr);
- SIVAL(req->out.body, 0x3C, io->smb2.out._pad);
+ SIVAL(req->out.body, 0x3C, io->smb2.out.reserved2);
smb2srv_push_handle(req->out.body, 0x40, io->smb2.out.file.ntvfs);
SMB2SRV_CHECK(smb2_push_o32s32_blob(&req->out, 0x50, io->smb2.out.blob));
@@ -64,22 +65,26 @@ void smb2srv_create_recv(struct smb2srv_request *req)
SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_create_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
io->smb2.level = RAW_OPEN_SMB2;
- io->smb2.in.oplock_flags = SVAL(req->in.body, 0x02);
- io->smb2.in.impersonation = IVAL(req->in.body, 0x04);
- io->smb2.in.unknown3[0] = IVAL(req->in.body, 0x08);
- io->smb2.in.unknown3[1] = IVAL(req->in.body, 0x0C);
- io->smb2.in.unknown3[2] = IVAL(req->in.body, 0x10);
- io->smb2.in.unknown3[3] = IVAL(req->in.body, 0x14);
- io->smb2.in.access_mask = IVAL(req->in.body, 0x18);
- io->smb2.in.file_attr = IVAL(req->in.body, 0x1C);
+ io->smb2.in.security_flags = CVAL(req->in.body, 0x02);
+ io->smb2.in.oplock_level = CVAL(req->in.body, 0x03);
+ io->smb2.in.impersonation_level = IVAL(req->in.body, 0x04);
+ io->smb2.in.create_flags = BVAL(req->in.body, 0x08);
+ io->smb2.in.reserved = BVAL(req->in.body, 0x10);
+ io->smb2.in.desired_access = IVAL(req->in.body, 0x18);
+ io->smb2.in.file_attributes = IVAL(req->in.body, 0x1C);
io->smb2.in.share_access = IVAL(req->in.body, 0x20);
- io->smb2.in.open_disposition = IVAL(req->in.body, 0x24);
+ io->smb2.in.create_disposition = IVAL(req->in.body, 0x24);
io->smb2.in.create_options = IVAL(req->in.body, 0x28);
SMB2SRV_CHECK(smb2_pull_o16s16_string(&req->in, io, req->in.body+0x2C, &io->smb2.in.fname));
SMB2SRV_CHECK(smb2_pull_o32s32_blob(&req->in, io, req->in.body+0x30, &blob));
/* TODO: parse the blob */
ZERO_STRUCT(io->smb2.in.eas);
+ /* the VFS backend does not yet handle NULL filenames */
+ if (io->smb2.in.fname == NULL) {
+ io->smb2.in.fname = "";
+ }
+
SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, io));
}
diff --git a/source4/smb_server/smb2/find.c b/source4/smb_server/smb2/find.c
index c594adf7a0..6018f1958f 100644
--- a/source4/smb_server/smb2/find.c
+++ b/source4/smb_server/smb2/find.c
@@ -161,6 +161,11 @@ void smb2srv_find_recv(struct smb2srv_request *req)
SMB2SRV_CHECK(smb2_pull_o16s16_string(&req->in, info, req->in.body+0x18, &info->in.pattern));
info->in.max_response_size = IVAL(req->in.body, 0x1C);
+ /* the VFS backend does not yet handle NULL patterns */
+ if (info->in.pattern == NULL) {
+ info->in.pattern = "";
+ }
+
SMB2SRV_CHECK_FILE_HANDLE(info->in.file.ntvfs);
SMB2SRV_CALL_NTVFS_BACKEND(smb2srv_find_backend(state));
}
diff --git a/source4/smb_server/smb2/negprot.c b/source4/smb_server/smb2/negprot.c
index 8e3cfd3547..5bbd7f7d5e 100644
--- a/source4/smb_server/smb2/negprot.c
+++ b/source4/smb_server/smb2/negprot.c
@@ -21,6 +21,7 @@
#include "includes.h"
#include "auth/credentials/credentials.h"
#include "auth/gensec/gensec.h"
+#include "libcli/raw/libcliraw.h"
#include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h"
#include "smb_server/smb_server.h"
@@ -92,24 +93,33 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2
struct timeval current_time;
struct timeval boot_time;
+ /* we only do one dialect for now */
+ if (io->in.dialect_count < 1) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+ if (io->in.dialects[0] != 0 &&
+ io->in.dialects[0] != SMB2_DIALECT_REVISION) {
+ DEBUG(0,("Got unexpected SMB2 dialect %u\n", io->in.dialects[0]));
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
req->smb_conn->negotiate.protocol = PROTOCOL_SMB2;
current_time = timeval_current(); /* TODO: handle timezone?! */
boot_time = timeval_current(); /* TODO: fix me */
- io->out._pad = 0;
- io->out.unknown2 = 0x06;
- ZERO_STRUCT(io->out.sessid);
- io->out.unknown3 = 0x0d;
- io->out.unknown4 = 0x00;
- io->out.unknown5 = 0x01;
- io->out.unknown6 = 0x01;
- io->out.unknown7 = 0x01;
- io->out.current_time = timeval_to_nttime(&current_time);
- io->out.boot_time = timeval_to_nttime(&boot_time);
+ ZERO_STRUCT(io->out);
+ io->out.security_mode = 0; /* no signing yet */
+ io->out.dialect_revision = SMB2_DIALECT_REVISION;
+ io->out.capabilities = 0;
+ io->out.max_transact_size = 0x10000;
+ io->out.max_read_size = 0x10000;
+ io->out.max_write_size = 0x10000;
+ io->out.system_time = timeval_to_nttime(&current_time);
+ io->out.server_start_time = timeval_to_nttime(&boot_time);
+ io->out.reserved2 = 0;
status = smb2srv_negprot_secblob(req, &io->out.secblob);
NT_STATUS_NOT_OK_RETURN(status);
- io->out.unknown9 = 0x204d4c20;
return NT_STATUS_OK;
}
@@ -117,6 +127,7 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2
static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negprot *io)
{
NTSTATUS status;
+ enum ndr_err_code ndr_err;
if (NT_STATUS_IS_ERR(req->status)) {
smb2srv_send_error(req, req->status); /* TODO: is this correct? */
@@ -130,16 +141,22 @@ static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negpro
return;
}
- SSVAL(req->out.body, 0x02, io->out._pad);
- SIVAL(req->out.body, 0x04, io->out.unknown2);
- memcpy(req->out.body+0x08, io->out.sessid, 16);
- SIVAL(req->out.body, 0x18, io->out.unknown3);
- SSVAL(req->out.body, 0x1C, io->out.unknown4);
- SIVAL(req->out.body, 0x1E, io->out.unknown5);
- SIVAL(req->out.body, 0x22, io->out.unknown6);
- SSVAL(req->out.body, 0x26, io->out.unknown7);
- push_nttime(req->out.body, 0x28, io->out.current_time);
- push_nttime(req->out.body, 0x30, io->out.boot_time);
+ SSVAL(req->out.body, 0x02, io->out.security_mode);
+ SIVAL(req->out.body, 0x04, io->out.dialect_revision);
+ SIVAL(req->out.body, 0x06, io->out.reserved);
+ ndr_err = smbcli_push_guid(req->out.body, 0x08, &io->out.server_guid);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
+ talloc_free(req);
+ return;
+ }
+ SIVAL(req->out.body, 0x18, io->out.capabilities);
+ SIVAL(req->out.body, 0x1C, io->out.max_transact_size);
+ SIVAL(req->out.body, 0x20, io->out.max_read_size);
+ SIVAL(req->out.body, 0x24, io->out.max_write_size);
+ push_nttime(req->out.body, 0x28, io->out.system_time);
+ push_nttime(req->out.body, 0x30, io->out.server_start_time);
+ SIVAL(req->out.body, 0x3C, io->out.reserved2);
status = smb2_push_o16s16_blob(&req->out, 0x38, io->out.secblob);
if (!NT_STATUS_IS_OK(status)) {
smbsrv_terminate_connection(req->smb_conn, nt_errstr(status));
@@ -147,14 +164,14 @@ static void smb2srv_negprot_send(struct smb2srv_request *req, struct smb2_negpro
return;
}
- SIVAL(req->out.body, 0x3C, io->out.unknown9);
-
smb2srv_send_reply(req);
}
void smb2srv_negprot_recv(struct smb2srv_request *req)
{
struct smb2_negprot *io;
+ int i;
+ enum ndr_err_code ndr_err;
if (req->in.body_size < 0x26) {
smb2srv_send_error(req, NT_STATUS_FOOBAR);
@@ -168,9 +185,27 @@ void smb2srv_negprot_recv(struct smb2srv_request *req)
return;
}
- io->in.unknown1 = SVAL(req->in.body, 0x02);
- memcpy(io->in.unknown2, req->in.body + 0x04, 0x20);
- io->in.unknown3 = SVAL(req->in.body, 0x24);
+ io->in.dialect_count = SVAL(req->in.body, 0x02);
+ io->in.security_mode = SVAL(req->in.body, 0x04);
+ io->in.reserved = SVAL(req->in.body, 0x06);
+ 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));
+ talloc_free(req);
+ return;
+ }
+ io->in.start_time = smbcli_pull_nttime(req->in.body, 0x1C);
+
+ io->in.dialects = talloc_array(req, uint16_t, io->in.dialect_count);
+ if (io->in.dialects == NULL) {
+ smbsrv_terminate_connection(req->smb_conn, nt_errstr(NT_STATUS_NO_MEMORY));
+ talloc_free(req);
+ return;
+ }
+ for (i=0;i<io->in.dialect_count;i++) {
+ io->in.dialects[i] = SVAL(req->in.body, 0x24+i*2);
+ }
req->status = smb2srv_negprot_backend(req, io);
@@ -182,14 +217,13 @@ void smb2srv_negprot_recv(struct smb2srv_request *req)
}
/*
- * reply to a SMB negprot request with dialect "SMB 2.001"
+ * reply to a SMB negprot request with dialect "SMB 2.002"
*/
void smb2srv_reply_smb_negprot(struct smbsrv_request *smb_req)
{
struct smb2srv_request *req;
uint32_t body_fixed_size = 0x26;
- /* create a fake SMB2 negprot request */
req = talloc_zero(smb_req->smb_conn, struct smb2srv_request);
if (!req) goto nomem;
req->smb_conn = smb_req->smb_conn;
@@ -205,19 +239,21 @@ void smb2srv_reply_smb_negprot(struct smbsrv_request *smb_req)
req->in.body_size = body_fixed_size;
req->in.dynamic = NULL;
+ smb2srv_setup_bufinfo(req);
+
SIVAL(req->in.hdr, 0, SMB2_MAGIC);
SSVAL(req->in.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
- SSVAL(req->in.hdr, SMB2_HDR_PAD1, 0);
+ SSVAL(req->in.hdr, SMB2_HDR_EPOCH, 0);
SIVAL(req->in.hdr, SMB2_HDR_STATUS, 0);
SSVAL(req->in.hdr, SMB2_HDR_OPCODE, SMB2_OP_NEGPROT);
- SSVAL(req->in.hdr, SMB2_HDR_UNKNOWN1, 0);
+ SSVAL(req->in.hdr, SMB2_HDR_CREDIT, 0);
SIVAL(req->in.hdr, SMB2_HDR_FLAGS, 0);
- SIVAL(req->in.hdr, SMB2_HDR_CHAIN_OFFSET, 0);
- SBVAL(req->in.hdr, SMB2_HDR_SEQNUM, 0);
+ SIVAL(req->in.hdr, SMB2_HDR_NEXT_COMMAND, 0);
+ SBVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID, 0);
SIVAL(req->in.hdr, SMB2_HDR_PID, 0);
SIVAL(req->in.hdr, SMB2_HDR_TID, 0);
- SBVAL(req->in.hdr, SMB2_HDR_UID, 0);
- memset(req->in.hdr+SMB2_HDR_SIG, 0, 16);
+ SBVAL(req->in.hdr, SMB2_HDR_SESSION_ID, 0);
+ memset(req->in.hdr+SMB2_HDR_SIGNATURE, 0, 16);
/* this seems to be a bug, they use 0x24 but the length is 0x26 */
SSVAL(req->in.body, 0x00, 0x24);
diff --git a/source4/smb_server/smb2/receive.c b/source4/smb_server/smb2/receive.c
index cfae2dbe52..dea7c9e79e 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.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;
+ 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);
@@ -94,17 +110,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));
@@ -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,
@@ -259,10 +277,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);
@@ -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
diff --git a/source4/smb_server/smb2/sesssetup.c b/source4/smb_server/smb2/sesssetup.c
index 636f5f0e27..1aaacf897c 100644
--- a/source4/smb_server/smb2/sesssetup.c
+++ b/source4/smb_server/smb2/sesssetup.c
@@ -32,12 +32,12 @@
static void smb2srv_sesssetup_send(struct smb2srv_request *req, union smb_sesssetup *io)
{
- uint16_t unknown1;
+ uint16_t credit;
if (NT_STATUS_IS_OK(req->status)) {
- unknown1 = 0x0003;
+ credit = 0x0003;
} else if (NT_STATUS_EQUAL(req->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- unknown1 = 0x0002;
+ credit = 0x0002;
} else {
smb2srv_send_error(req, req->status);
return;
@@ -45,10 +45,10 @@ static void smb2srv_sesssetup_send(struct smb2srv_request *req, union smb_sessse
SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, true, io->smb2.out.secblob.length));
- SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1, unknown1);
- SBVAL(req->out.hdr, SMB2_HDR_UID, io->smb2.out.uid);
+ SSVAL(req->out.hdr, SMB2_HDR_CREDIT, credit);
+ SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, io->smb2.out.uid);
- SSVAL(req->out.body, 0x02, io->smb2.out._pad);
+ SSVAL(req->out.body, 0x02, io->smb2.out.session_flags);
SMB2SRV_CHECK(smb2_push_o16s16_blob(&req->out, 0x04, io->smb2.out.secblob));
smb2srv_send_reply(req);
@@ -108,11 +108,11 @@ static void smb2srv_sesssetup_backend(struct smb2srv_request *req, union smb_ses
struct smbsrv_session *smb_sess = NULL;
uint64_t vuid;
- io->smb2.out._pad = 0;
+ io->smb2.out.session_flags = 0;
io->smb2.out.uid = 0;
io->smb2.out.secblob = data_blob(NULL, 0);
- vuid = BVAL(req->in.hdr, SMB2_HDR_UID);
+ vuid = BVAL(req->in.hdr, SMB2_HDR_SESSION_ID);
/*
* only when we got '0' we should allocate a new session
@@ -192,12 +192,13 @@ void smb2srv_sesssetup_recv(struct smb2srv_request *req)
SMB2SRV_CHECK_BODY_SIZE(req, 0x18, true);
SMB2SRV_TALLOC_IO_PTR(io, union smb_sesssetup);
- io->smb2.level = RAW_SESSSETUP_SMB2;
- io->smb2.in._pad = SVAL(req->in.body, 0x02);
- io->smb2.in.unknown2 = IVAL(req->in.body, 0x04);
- io->smb2.in.unknown3 = IVAL(req->in.body, 0x08);
+ io->smb2.level = RAW_SESSSETUP_SMB2;
+ io->smb2.in.vc_number = CVAL(req->in.body, 0x02);
+ io->smb2.in.security_mode = CVAL(req->in.body, 0x03);
+ io->smb2.in.capabilities = IVAL(req->in.body, 0x04);
+ io->smb2.in.channel = IVAL(req->in.body, 0x08);
+ io->smb2.in.previous_sessionid = BVAL(req->in.body, 0x10);
SMB2SRV_CHECK(smb2_pull_o16s16_blob(&req->in, io, req->in.body+0x0C, &io->smb2.in.secblob));
- io->smb2.in.unknown4 = BVAL(req->in.body, 0x10);
smb2srv_sesssetup_backend(req, io);
}
diff --git a/source4/smb_server/smb2/tcon.c b/source4/smb_server/smb2/tcon.c
index 6d0d98554c..7f7d558b16 100644
--- a/source4/smb_server/smb2/tcon.c
+++ b/source4/smb_server/smb2/tcon.c
@@ -55,26 +55,28 @@ static NTSTATUS smb2srv_send_oplock_break(void *p, struct ntvfs_handle *h, uint8
req->seqnum = UINT64_MAX;
+ smb2srv_setup_bufinfo(req);
+
SIVAL(req->in.hdr, 0, SMB2_MAGIC);
SSVAL(req->in.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
- SSVAL(req->in.hdr, SMB2_HDR_PAD1, 0);
+ SSVAL(req->in.hdr, SMB2_HDR_EPOCH, 0);
SIVAL(req->in.hdr, SMB2_HDR_STATUS, 0);
SSVAL(req->in.hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
- SSVAL(req->in.hdr, SMB2_HDR_UNKNOWN1, 0);
+ SSVAL(req->in.hdr, SMB2_HDR_CREDIT, 0);
SIVAL(req->in.hdr, SMB2_HDR_FLAGS, 0);
- SIVAL(req->in.hdr, SMB2_HDR_CHAIN_OFFSET, 0);
- SBVAL(req->in.hdr, SMB2_HDR_SEQNUM, 0);
+ SIVAL(req->in.hdr, SMB2_HDR_NEXT_COMMAND, 0);
+ SBVAL(req->in.hdr, SMB2_HDR_MESSAGE_ID, 0);
SIVAL(req->in.hdr, SMB2_HDR_PID, 0);
SIVAL(req->in.hdr, SMB2_HDR_TID, 0);
- SBVAL(req->in.hdr, SMB2_HDR_UID, 0);
- memset(req->in.hdr+SMB2_HDR_SIG, 0, 16);
+ SBVAL(req->in.hdr, SMB2_HDR_SESSION_ID, 0);
+ memset(req->in.hdr+SMB2_HDR_SIGNATURE, 0, 16);
SSVAL(req->in.body, 0, 2);
status = smb2srv_setup_reply(req, 0x18, false, 0);
NT_STATUS_NOT_OK_RETURN(status);
- SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1, 0x0000);
+ SSVAL(req->out.hdr, SMB2_HDR_CREDIT, 0x0000);
SSVAL(req->out.body, 0x02, 0x0001);
SIVAL(req->out.body, 0x04, 0x00000000);
@@ -240,8 +242,6 @@ static NTSTATUS smb2srv_tcon_backend(struct smb2srv_request *req, union smb_tcon
struct smbsrv_tcon *tcon;
NTSTATUS status;
enum ntvfs_type type;
- uint16_t type_smb2;
- uint32_t unknown2;
const char *service = io->smb2.in.path;
struct share_config *scfg;
const char *sharetype;
@@ -270,16 +270,10 @@ static NTSTATUS smb2srv_tcon_backend(struct smb2srv_request *req, union smb_tcon
sharetype = share_string_option(scfg, SHARE_TYPE, "DISK");
if (sharetype && strcmp(sharetype, "IPC") == 0) {
type = NTVFS_IPC;
- type_smb2 = 0x0002;
- unknown2 = 0x00000030;
} else if (sharetype && strcmp(sharetype, "PRINTER") == 0) {
type = NTVFS_PRINT;
- type_smb2 = 0x0003;
- unknown2 = 0x00000000;
} else {
type = NTVFS_DISK;
- type_smb2 = 0x0001;
- unknown2 = 0x00000800;
}
tcon = smbsrv_smb2_tcon_new(req->session, scfg->name);
@@ -344,10 +338,11 @@ static NTSTATUS smb2srv_tcon_backend(struct smb2srv_request *req, union smb_tcon
goto failed;
}
- io->smb2.out.unknown1 = type_smb2; /* 1 - DISK, 2 - Print, 3 - IPC */
- io->smb2.out.unknown2 = unknown2;
- io->smb2.out.unknown3 = 0x00000000;
- io->smb2.out.access_mask= SEC_RIGHTS_FILE_ALL;
+ io->smb2.out.share_type = (unsigned)type; /* 1 - DISK, 2 - Print, 3 - IPC */
+ io->smb2.out.reserved = 0;
+ io->smb2.out.flags = 0x00000000;
+ io->smb2.out.capabilities = 0;
+ io->smb2.out.access_mask = SEC_RIGHTS_FILE_ALL;
io->smb2.out.tid = tcon->tid;
@@ -361,27 +356,28 @@ failed:
static void smb2srv_tcon_send(struct smb2srv_request *req, union smb_tcon *io)
{
- uint16_t unknown1;
+ uint16_t credit;
if (!NT_STATUS_IS_OK(req->status)) {
smb2srv_send_error(req, req->status);
return;
}
- if (io->smb2.out.unknown1 == 0x0002) {
+ if (io->smb2.out.share_type == NTVFS_IPC) {
/* if it's an IPC share vista returns 0x0005 */
- unknown1 = 0x0005;
+ credit = 0x0005;
} else {
- unknown1 = 0x0001;
+ credit = 0x0001;
}
SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x10, false, 0));
SIVAL(req->out.hdr, SMB2_HDR_TID, io->smb2.out.tid);
- SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1,unknown1);
+ SSVAL(req->out.hdr, SMB2_HDR_CREDIT,credit);
- SSVAL(req->out.body, 0x02, io->smb2.out.unknown1);
- SIVAL(req->out.body, 0x04, io->smb2.out.unknown2);
- SIVAL(req->out.body, 0x08, io->smb2.out.unknown3);
+ SCVAL(req->out.body, 0x02, io->smb2.out.share_type);
+ SCVAL(req->out.body, 0x03, io->smb2.out.reserved);
+ SIVAL(req->out.body, 0x04, io->smb2.out.flags);
+ SIVAL(req->out.body, 0x08, io->smb2.out.capabilities);
SIVAL(req->out.body, 0x0C, io->smb2.out.access_mask);
smb2srv_send_reply(req);
@@ -395,9 +391,14 @@ void smb2srv_tcon_recv(struct smb2srv_request *req)
SMB2SRV_TALLOC_IO_PTR(io, union smb_tcon);
io->smb2.level = RAW_TCON_SMB2;
- io->smb2.in.unknown1 = SVAL(req->in.body, 0x02);
+ io->smb2.in.reserved = SVAL(req->in.body, 0x02);
SMB2SRV_CHECK(smb2_pull_o16s16_string(&req->in, io, req->in.body+0x04, &io->smb2.in.path));
+ /* the VFS backend does not yet handle NULL paths */
+ if (io->smb2.in.path == NULL) {
+ io->smb2.in.path = "";
+ }
+
req->status = smb2srv_tcon_backend(req, io);
if (req->control_flags & SMB2SRV_REQ_CTRL_FLAG_NOT_REPLY) {