diff options
Diffstat (limited to 'source4/smb_server/smb2')
-rw-r--r-- | source4/smb_server/smb2/config.mk | 1 | ||||
-rw-r--r-- | source4/smb_server/smb2/fileinfo.c | 49 | ||||
-rw-r--r-- | source4/smb_server/smb2/fileio.c | 27 | ||||
-rw-r--r-- | source4/smb_server/smb2/find.c | 5 | ||||
-rw-r--r-- | source4/smb_server/smb2/negprot.c | 104 | ||||
-rw-r--r-- | source4/smb_server/smb2/receive.c | 38 | ||||
-rw-r--r-- | source4/smb_server/smb2/sesssetup.c | 27 | ||||
-rw-r--r-- | source4/smb_server/smb2/tcon.c | 57 |
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(¤t_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(¤t_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) { |