diff options
26 files changed, 453 insertions, 329 deletions
diff --git a/source4/libcli/raw/clisession.c b/source4/libcli/raw/clisession.c index 2942279b12..9e114aece8 100644 --- a/source4/libcli/raw/clisession.c +++ b/source4/libcli/raw/clisession.c @@ -137,6 +137,9 @@ struct smbcli_request *smb_raw_sesssetup_send(struct smbcli_session *session, smbcli_req_append_string(req, parms->spnego.in.lanman, STR_TERMINATE); smbcli_req_append_string(req, parms->spnego.in.workgroup, STR_TERMINATE); break; + + case RAW_SESSSETUP_SMB2: + return NULL; } if (!smbcli_request_send(req)) { @@ -213,6 +216,10 @@ NTSTATUS smb_raw_sesssetup_recv(struct smbcli_request *req, p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE); p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.workgroup, p, -1, STR_TERMINATE); break; + + case RAW_SESSSETUP_SMB2: + req->status = NT_STATUS_INTERNAL_ERROR; + break; } failed: diff --git a/source4/libcli/raw/clitree.c b/source4/libcli/raw/clitree.c index 6e120ed615..51f2e12457 100644 --- a/source4/libcli/raw/clitree.c +++ b/source4/libcli/raw/clitree.c @@ -79,6 +79,9 @@ struct smbcli_request *smb_raw_tcon_send(struct smbcli_tree *tree, smbcli_req_append_string(req, parms->tconx.in.path, STR_TERMINATE | STR_UPPER); smbcli_req_append_string(req, parms->tconx.in.device, STR_TERMINATE | STR_ASCII); break; + + case RAW_TCON_SMB2: + return NULL; } if (!smbcli_request_send(req)) { @@ -125,6 +128,10 @@ NTSTATUS smb_raw_tcon_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, p += smbcli_req_pull_string(req, mem_ctx, &parms->tconx.out.fs_type, p, -1, STR_TERMINATE); break; + + case RAW_TCON_SMB2: + req->status = NT_STATUS_INTERNAL_ERROR; + break; } failed: diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h index 588237acb0..5fe64f064c 100644 --- a/source4/libcli/raw/interfaces.h +++ b/source4/libcli/raw/interfaces.h @@ -207,7 +207,11 @@ union smb_rename { } ntrename; }; -enum smb_tcon_level {RAW_TCON_TCON, RAW_TCON_TCONX}; +enum smb_tcon_level { + RAW_TCON_TCON, + RAW_TCON_TCONX, + RAW_TCON_SMB2 +}; /* union used in tree connect call */ union smb_tcon { @@ -248,10 +252,42 @@ union smb_tcon { uint16_t tid; } out; } tconx; + + /* SMB2 TreeConnect */ + struct smb2_tree_connect { + enum smb_tcon_level level; + + struct { + /* static body buffer 8 (0x08) bytes */ + /* uint16_t buffer_code; 0x09 = 0x08 + 1 */ + uint16_t unknown1; /* 0x0000 */ + /* uint16_t path_ofs */ + /* uint16_t path_size */ + + /* dynamic body */ + const char *path; /* as non-terminated UTF-16 on the wire */ + } in; + struct { + /* static body buffer 16 (0x10) bytes */ + /* uint16_t buffer_code; 0x10 */ + uint16_t unknown1; /* 0x02 */ + uint32_t unknown2; /* 0x00 */ + uint32_t unknown3; /* 0x00 */ + uint32_t access_mask; + + /* extracted from the SMB2 header */ + uint32_t tid; + } out; + } smb2; }; -enum smb_sesssetup_level {RAW_SESSSETUP_OLD, RAW_SESSSETUP_NT1, RAW_SESSSETUP_SPNEGO}; +enum smb_sesssetup_level { + RAW_SESSSETUP_OLD, + RAW_SESSSETUP_NT1, + RAW_SESSSETUP_SPNEGO, + RAW_SESSSETUP_SMB2 +}; /* union used in session_setup call */ union smb_sesssetup { @@ -330,6 +366,37 @@ union smb_sesssetup { uint16_t vuid; } out; } spnego; + + /* SMB2 SessionSetup */ + struct smb2_session_setup { + enum smb_sesssetup_level level; + + struct { + /* static body buffer 16 (0x10) bytes */ + /* uint16_t buffer_code; 0x11 = 0x10 + 1 */ + uint16_t _pad; + uint32_t unknown2; /* 0xF */ + uint32_t unknown3; /* 0x00 */ + /* uint16_t secblob_ofs */ + /* uint16_t secblob_size */ + + /* dynamic body */ + DATA_BLOB secblob; + } in; + struct { + /* static body buffer 8 (0x08) bytes */ + /* uint16_t buffer_code; 0x09 = 0x08 +1 */ + uint16_t _pad; + /* uint16_t secblob_ofs */ + /* uint16_t secblob_size */ + + /* dynamic body */ + DATA_BLOB secblob; + + /* extracted from the SMB2 header */ + uint64_t uid; + } out; + } smb2; }; /* Note that the specified enum values are identical to the actual info-levels used @@ -1161,12 +1228,18 @@ union smb_fsinfo { enum smb_open_level { - RAW_OPEN_OPEN, RAW_OPEN_OPENX, - RAW_OPEN_MKNEW, RAW_OPEN_CREATE, - RAW_OPEN_CTEMP, RAW_OPEN_SPLOPEN, - RAW_OPEN_NTCREATEX, RAW_OPEN_T2OPEN, - RAW_OPEN_NTTRANS_CREATE, - RAW_OPEN_OPENX_READX}; + RAW_OPEN_OPEN, + RAW_OPEN_OPENX, + RAW_OPEN_MKNEW, + RAW_OPEN_CREATE, + RAW_OPEN_CTEMP, + RAW_OPEN_SPLOPEN, + RAW_OPEN_NTCREATEX, + RAW_OPEN_T2OPEN, + RAW_OPEN_NTTRANS_CREATE, + RAW_OPEN_OPENX_READX, + RAW_OPEN_SMB2 +}; /* the generic interface is defined to be equal to the NTCREATEX interface */ #define RAW_OPEN_GENERIC RAW_OPEN_NTCREATEX @@ -1417,11 +1490,73 @@ union smb_open { uint16_t nread; } out; } openxreadx; + +#define SMB2_CREATE_FLAG_REQUEST_OPLOCK 0x0100 +#define SMB2_CREATE_FLAG_REQUEST_EXCLUSIVE_OPLOCK 0x0800 +#define SMB2_CREATE_FLAG_GRANT_OPLOCK 0x0001 +#define SMB2_CREATE_FLAG_GRANT_EXCLUSIVE_OPLOCK 0x0080 + + /* SMB2 Create */ + struct smb2_create { + enum smb_open_level level; + struct { + /* static body buffer 56 (0x38) bytes */ + /* uint16_t buffer_code; 0x39 = 0x38 + 1 */ + uint16_t oplock_flags; /* SMB2_CREATE_FLAG_* */ + uint32_t impersonation; + uint32_t unknown3[4]; + uint32_t access_mask; + + uint32_t file_attr; + uint32_t share_access; + uint32_t open_disposition; + uint32_t create_options; + + /* uint16_t fname_ofs */ + /* uint16_t fname_size */ + /* uint32_t blob_ofs; */ + /* uint32_t blob_size; */ + + /* dynamic body */ + const char *fname; + + /* optional list of extended attributes */ + struct smb_ea_list eas; + } in; + struct { + union smb_handle file; + + /* static body buffer 88 (0x58) bytes */ + /* uint16_t buffer_code; 0x59 = 0x58 + 1 */ + uint16_t oplock_flags; /* SMB2_CREATE_FLAG_* */ + uint32_t create_action; + NTTIME create_time; + NTTIME access_time; + NTTIME write_time; + NTTIME change_time; + uint64_t alloc_size; + uint64_t size; + uint32_t file_attr; + uint32_t _pad; + /* struct smb2_handle handle;*/ + /* uint32_t blob_ofs; */ + /* uint32_t blob_size; */ + + /* dynamic body */ + DATA_BLOB blob; + } out; + } smb2; }; -enum smb_read_level {RAW_READ_READBRAW, RAW_READ_LOCKREAD, RAW_READ_READ, RAW_READ_READX}; +enum smb_read_level { + RAW_READ_READBRAW, + RAW_READ_LOCKREAD, + RAW_READ_READ, + RAW_READ_READX, + RAW_READ_SMB2 +}; #define RAW_READ_GENERIC RAW_READ_READX @@ -1496,12 +1631,45 @@ union smb_read { uint16_t nread; } out; } read; + + /* SMB2 Read */ + struct smb2_read { + enum smb_read_level level; + struct { + union smb_handle file; + + /* static body buffer 48 (0x30) bytes */ + /* uint16_t buffer_code; 0x31 = 0x30 + 1 */ + uint16_t _pad; + uint32_t length; + uint64_t offset; + /* struct smb2_handle handle; */ + uint64_t unknown1; /* 0x0000000000000000 */ + uint64_t unknown2; /* 0x0000000000000000 */ + uint8_t _bug; + } in; + struct { + /* static body buffer 16 (0x10) bytes */ + /* uint16_t buffer_code; 0x11 = 0x10 + 1 */ + /* uint16_t data_ofs; */ + /* uint32_t data_size; */ + uint64_t unknown1; /* 0x0000000000000000 */ + + /* dynamic body */ + DATA_BLOB data; + } out; + } smb2; }; -enum smb_write_level {RAW_WRITE_WRITEUNLOCK, RAW_WRITE_WRITE, - RAW_WRITE_WRITEX, RAW_WRITE_WRITECLOSE, - RAW_WRITE_SPLWRITE}; +enum smb_write_level { + RAW_WRITE_WRITEUNLOCK, + RAW_WRITE_WRITE, + RAW_WRITE_WRITEX, + RAW_WRITE_WRITECLOSE, + RAW_WRITE_SPLWRITE, + RAW_WRITE_SMB2 +}; #define RAW_WRITE_GENERIC RAW_WRITE_WRITEX @@ -1579,6 +1747,34 @@ union smb_write { const uint8_t *data; } in; } splwrite; + + /* SMB2 Write */ + struct smb2_write { + enum smb_write_level level; + struct { + union smb_handle file; + + /* static body buffer 48 (0x30) bytes */ + /* uint16_t buffer_code; 0x31 = 0x30 + 1 */ + /* uint16_t data_ofs; */ + /* uint32_t data_size; */ + uint64_t offset; + /* struct smb2_handle handle; */ + uint64_t unknown1; /* 0xFFFFFFFFFFFFFFFF */ + uint64_t unknown2; /* 0xFFFFFFFFFFFFFFFF */ + + /* dynamic body */ + DATA_BLOB data; + } in; + struct { + /* static body buffer 17 (0x11) bytes */ + /* uint16_t buffer_code; 0x11 */ + uint16_t _pad; + uint32_t nwritten; + uint64_t unknown1; /* 0x0000000000000000 */ + uint8_t _bug; + } out; + } smb2; }; @@ -1619,7 +1815,11 @@ union smb_lock { }; -enum smb_close_level {RAW_CLOSE_CLOSE, RAW_CLOSE_SPLCLOSE}; +enum smb_close_level { + RAW_CLOSE_CLOSE, + RAW_CLOSE_SPLCLOSE, + RAW_CLOSE_SMB2 +}; #define RAW_CLOSE_GENERIC RAW_CLOSE_CLOSE @@ -1643,6 +1843,33 @@ union smb_close { union smb_handle file; } in; } splclose; + + /* SMB2 Close */ + struct smb2_close { + enum smb_close_level level; + struct { + union smb_handle file; + + /* static body buffer 24 (0x18) bytes */ + /* uint16_t buffer_code; 0x18 */ +#define SMB2_CLOSE_FLAGS_FULL_INFORMATION (1<<0) + uint16_t flags; /* SMB2_CLOSE_FLAGS_* */ + uint32_t _pad; + } in; + struct { + /* static body buffer 60 (0x3C) bytes */ + /* uint16_t buffer_code; 0x3C */ + uint16_t flags; + uint32_t _pad; + NTTIME create_time; + NTTIME access_time; + NTTIME write_time; + NTTIME change_time; + uint64_t alloc_size; + uint64_t size; + uint32_t file_attr; + } out; + } smb2; }; @@ -1681,7 +1908,11 @@ union smb_lpq { } retq; }; -enum smb_ioctl_level {RAW_IOCTL_IOCTL, RAW_IOCTL_NTIOCTL}; +enum smb_ioctl_level { + RAW_IOCTL_IOCTL, + RAW_IOCTL_NTIOCTL, + RAW_IOCTL_SMB2 +}; /* union for ioctl() backend @@ -1723,12 +1954,60 @@ union smb_ioctl { DATA_BLOB blob; } out; } ntioctl; + + /* SMB2 Ioctl */ + struct smb2_ioctl { + enum smb_ioctl_level level; + struct { + union smb_handle file; + + /* static body buffer 56 (0x38) bytes */ + /* uint16_t buffer_code; 0x39 = 0x38 + 1 */ + uint16_t _pad; + uint32_t function; + /*struct smb2_handle handle;*/ + /* uint32_t out_ofs; */ + /* uint32_t out_size; */ + uint32_t unknown2; + /* uint32_t in_ofs; */ + /* uint32_t in_size; */ + uint32_t max_response_size; + uint64_t flags; + + /* dynamic body */ + DATA_BLOB out; + DATA_BLOB in; + } in; + struct { + union smb_handle file; + + /* static body buffer 48 (0x30) bytes */ + /* uint16_t buffer_code; 0x31 = 0x30 + 1 */ + uint16_t _pad; + uint32_t function; + /* struct smb2_handle handle; */ + /* uint32_t in_ofs; */ + /* uint32_t in_size; */ + /* uint32_t out_ofs; */ + /* uint32_t out_size; */ + uint32_t unknown2; + uint32_t unknown3; + + /* dynamic body */ + DATA_BLOB in; + DATA_BLOB out; + } out; + } smb2; }; -enum smb_flush_level {RAW_FLUSH_FLUSH, RAW_FLUSH_ALL}; +enum smb_flush_level { + RAW_FLUSH_FLUSH, + RAW_FLUSH_ALL, + RAW_FLUSH_SMB2 +}; -/* struct for SMBflush */ union smb_flush { + /* struct for SMBflush */ struct { enum smb_flush_level level; struct { @@ -1736,11 +2015,20 @@ union smb_flush { } in; } flush, generic; + /* SMBflush with 0xFFFF wildcard fnum */ struct { enum smb_flush_level level; } flush_all; -}; + /* SMB2 Flush */ + struct smb2_flush { + enum smb_flush_level level; + struct { + union smb_handle file; + uint32_t unknown; + } in; + } smb2; +}; /* struct for SMBcopy */ struct smb_copy { @@ -1823,7 +2111,8 @@ struct smb_notify { enum smb_search_level {RAW_SEARCH_GENERIC = 0xF000, RAW_SEARCH_SEARCH, /* SMBsearch */ RAW_SEARCH_FFIRST, /* SMBffirst */ - RAW_SEARCH_FUNIQUE, /* SMBfunique */ + RAW_SEARCH_FUNIQUE, /* SMBfunique */ + RAW_SEARCH_SMB2, /* SMB2 Find */ RAW_SEARCH_STANDARD = SMB_FIND_STANDARD, RAW_SEARCH_EA_SIZE = SMB_FIND_EA_SIZE, RAW_SEARCH_EA_LIST = SMB_FIND_EA_LIST, @@ -1878,6 +2167,45 @@ union smb_search_first { uint16_t end_of_search; } out; } t2ffirst; + +/* + SMB2 uses different level numbers for the same old SMB search levels +*/ +#define SMB2_FIND_DIRECTORY_INFO 0x01 +#define SMB2_FIND_FULL_DIRECTORY_INFO 0x02 +#define SMB2_FIND_BOTH_DIRECTORY_INFO 0x03 +#define SMB2_FIND_NAME_INFO 0x0C +#define SMB2_FIND_ID_BOTH_DIRECTORY_INFO 0x25 +#define SMB2_FIND_ID_FULL_DIRECTORY_INFO 0x26 + /* SMB2 Find */ + struct smb2_find { + enum smb_search_level level; + struct { + union smb_handle file; + + /* static body buffer 32 (0x20) bytes */ + /* uint16_t buffer_code; 0x21 = 0x20 + 1 */ + uint8_t level; + uint8_t continue_flags; /* SMB2_CONTINUE_FLAG_* */ + uint32_t unknown; /* perhaps a continue token? */ + /* struct smb2_handle handle; */ + /* uint16_t pattern_ofs; */ + /* uint32_t pattern_size; */ + uint32_t max_response_size; + + /* dynamic body */ + const char *pattern; + } in; + struct { + /* static body buffer 8 (0x08) bytes */ + /* uint16_t buffer_code; 0x08 */ + /* uint16_t blob_ofs; */ + /* uint32_t blob_size; */ + + /* dynamic body */ + DATA_BLOB blob; + } out; + } smb2; }; /* union for file search continue */ diff --git a/source4/libcli/raw/rawfile.c b/source4/libcli/raw/rawfile.c index faa2cdbeb4..3aad05a748 100644 --- a/source4/libcli/raw/rawfile.c +++ b/source4/libcli/raw/rawfile.c @@ -545,6 +545,8 @@ struct smbcli_request *smb_raw_open_send(struct smbcli_tree *tree, union smb_ope SIVAL(req->out.vwv, VWV(10),parms->openxreadx.in.offset>>32); } break; + case RAW_OPEN_SMB2: + return NULL; } if (!smbcli_request_send(req)) { @@ -680,6 +682,9 @@ NTSTATUS smb_raw_open_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, unio req->status = NT_STATUS_BUFFER_TOO_SMALL; } break; + case RAW_OPEN_SMB2: + req->status = NT_STATUS_INTERNAL_ERROR; + break; } failed: @@ -717,6 +722,9 @@ struct smbcli_request *smb_raw_close_send(struct smbcli_tree *tree, union smb_cl SSVAL(req->out.vwv, VWV(0), parms->splclose.in.file.fnum); SIVAL(req->out.vwv, VWV(1), 0); /* reserved */ break; + + case RAW_CLOSE_SMB2: + return NULL; } if (!req) return NULL; @@ -858,6 +866,8 @@ struct smbcli_request *smb_raw_flush_send(struct smbcli_tree *tree, union smb_fl case RAW_FLUSH_ALL: fnum = 0xFFFF; break; + case RAW_FLUSH_SMB2: + return NULL; } SETUP_REQUEST(SMBflush, 1, 0); diff --git a/source4/libcli/raw/rawioctl.c b/source4/libcli/raw/rawioctl.c index af48fcb566..0bd37785ac 100644 --- a/source4/libcli/raw/rawioctl.c +++ b/source4/libcli/raw/rawioctl.c @@ -132,6 +132,9 @@ struct smbcli_request *smb_raw_ioctl_send(struct smbcli_tree *tree, union smb_io case RAW_IOCTL_NTIOCTL: req = smb_raw_ntioctl_send(tree, parms); break; + + case RAW_IOCTL_SMB2: + return NULL; } return req; @@ -149,6 +152,9 @@ NTSTATUS smb_raw_ioctl_recv(struct smbcli_request *req, case RAW_IOCTL_NTIOCTL: return smb_raw_ntioctl_recv(req, mem_ctx, parms); + + case RAW_IOCTL_SMB2: + break; } return NT_STATUS_INVALID_LEVEL; } diff --git a/source4/libcli/raw/rawreadwrite.c b/source4/libcli/raw/rawreadwrite.c index 63a60ad545..7a47ce66f4 100644 --- a/source4/libcli/raw/rawreadwrite.c +++ b/source4/libcli/raw/rawreadwrite.c @@ -94,6 +94,9 @@ struct smbcli_request *smb_raw_read_send(struct smbcli_tree *tree, union smb_rea SSVAL(req->out.hdr, HDR_FLG2, flags2); } break; + + case RAW_READ_SMB2: + return NULL; } if (!smbcli_request_send(req)) { @@ -165,6 +168,10 @@ NTSTATUS smb_raw_read_recv(struct smbcli_request *req, union smb_read *parms) req->status = NT_STATUS_BUFFER_TOO_SMALL; } break; + + case RAW_READ_SMB2: + req->status = NT_STATUS_INTERNAL_ERROR; + break; } failed: @@ -261,6 +268,9 @@ struct smbcli_request *smb_raw_write_send(struct smbcli_tree *tree, union smb_wr memcpy(req->out.data, parms->splwrite.in.data, parms->splwrite.in.count); } break; + + case RAW_WRITE_SMB2: + return NULL; } if (!smbcli_request_send(req)) { @@ -303,6 +313,9 @@ NTSTATUS smb_raw_write_recv(struct smbcli_request *req, union smb_write *parms) break; case RAW_WRITE_SPLWRITE: break; + case RAW_WRITE_SMB2: + req->status = NT_STATUS_INTERNAL_ERROR; + break; } failed: diff --git a/source4/libcli/raw/rawsearch.c b/source4/libcli/raw/rawsearch.c index e844a33358..5e05d7c3c5 100644 --- a/source4/libcli/raw/rawsearch.c +++ b/source4/libcli/raw/rawsearch.c @@ -482,6 +482,7 @@ static int parse_trans2_search(struct smbcli_tree *tree, case RAW_SEARCH_SEARCH: case RAW_SEARCH_FFIRST: case RAW_SEARCH_FUNIQUE: + case RAW_SEARCH_SMB2: /* handled elsewhere */ return -1; diff --git a/source4/libcli/smb2/close.c b/source4/libcli/smb2/close.c index 4483f3c75b..9156e7d10d 100644 --- a/source4/libcli/smb2/close.c +++ b/source4/libcli/smb2/close.c @@ -37,7 +37,7 @@ struct smb2_request *smb2_close_send(struct smb2_tree *tree, struct smb2_close * SSVAL(req->out.body, 0x02, io->in.flags); SIVAL(req->out.body, 0x04, 0); /* pad */ - smb2_push_handle(req->out.body+0x08, &io->in.handle); + smb2_push_handle(req->out.body+0x08, &io->in.file.handle); smb2_transport_send(req); diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c index 339258a0df..da21d090fd 100644 --- a/source4/libcli/smb2/create.c +++ b/source4/libcli/smb2/create.c @@ -144,7 +144,7 @@ NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct io->out.size = BVAL(req->in.body, 0x30); io->out.file_attr = IVAL(req->in.body, 0x38); io->out._pad = IVAL(req->in.body, 0x3C); - smb2_pull_handle(req->in.body+0x40, &io->out.handle); + smb2_pull_handle(req->in.body+0x40, &io->out.file.handle); status = smb2_pull_o32s32_blob(&req->in, mem_ctx, req->in.body+0x50, &io->out.blob); if (!NT_STATUS_IS_OK(status)) { smb2_request_destroy(req); diff --git a/source4/libcli/smb2/find.c b/source4/libcli/smb2/find.c index e811095f42..8f4d6c8301 100644 --- a/source4/libcli/smb2/find.c +++ b/source4/libcli/smb2/find.c @@ -39,7 +39,7 @@ struct smb2_request *smb2_find_send(struct smb2_tree *tree, struct smb2_find *io SCVAL(req->out.body, 0x02, io->in.level); SCVAL(req->out.body, 0x03, io->in.continue_flags); SIVAL(req->out.body, 0x04, io->in.unknown); - smb2_push_handle(req->out.body+0x08, &io->in.handle); + smb2_push_handle(req->out.body+0x08, &io->in.file.handle); status = smb2_push_o16s16_string(&req->out, 0x18, io->in.pattern); if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/libcli/smb2/flush.c b/source4/libcli/smb2/flush.c index 596eb26009..0eb5ed7a3b 100644 --- a/source4/libcli/smb2/flush.c +++ b/source4/libcli/smb2/flush.c @@ -36,7 +36,7 @@ struct smb2_request *smb2_flush_send(struct smb2_tree *tree, struct smb2_flush * SSVAL(req->out.body, 0x02, 0); /* pad? */ SIVAL(req->out.body, 0x04, io->in.unknown); - smb2_push_handle(req->out.body+0x08, &io->in.handle); + smb2_push_handle(req->out.body+0x08, &io->in.file.handle); smb2_transport_send(req); diff --git a/source4/libcli/smb2/ioctl.c b/source4/libcli/smb2/ioctl.c index ffe029e16e..a3ac2d9f47 100644 --- a/source4/libcli/smb2/ioctl.c +++ b/source4/libcli/smb2/ioctl.c @@ -38,7 +38,7 @@ struct smb2_request *smb2_ioctl_send(struct smb2_tree *tree, struct smb2_ioctl * SSVAL(req->out.body, 0x02, 0); /* pad */ SIVAL(req->out.body, 0x04, io->in.function); - smb2_push_handle(req->out.body+0x08, &io->in.handle); + smb2_push_handle(req->out.body+0x08, &io->in.file.handle); status = smb2_push_o32s32_blob(&req->out, 0x18, io->in.out); if (!NT_STATUS_IS_OK(status)) { @@ -80,7 +80,7 @@ NTSTATUS smb2_ioctl_recv(struct smb2_request *req, io->out._pad = SVAL(req->in.body, 0x02); io->out.function = IVAL(req->in.body, 0x04); - smb2_pull_handle(req->in.body+0x08, &io->out.handle); + smb2_pull_handle(req->in.body+0x08, &io->out.file.handle); status = smb2_pull_o32s32_blob(&req->in, mem_ctx, req->in.body+0x18, &io->out.in); if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/libcli/smb2/read.c b/source4/libcli/smb2/read.c index 82e9b13280..6806adb8f6 100644 --- a/source4/libcli/smb2/read.c +++ b/source4/libcli/smb2/read.c @@ -37,7 +37,7 @@ struct smb2_request *smb2_read_send(struct smb2_tree *tree, struct smb2_read *io SSVAL(req->out.body, 0x02, 0); /* pad */ SIVAL(req->out.body, 0x04, io->in.length); SBVAL(req->out.body, 0x08, io->in.offset); - smb2_push_handle(req->out.body+0x10, &io->in.handle); + smb2_push_handle(req->out.body+0x10, &io->in.file.handle); SBVAL(req->out.body, 0x20, io->in.unknown1); SBVAL(req->out.body, 0x28, io->in.unknown2); SCVAL(req->out.body, 0x30, io->in._bug); diff --git a/source4/libcli/smb2/smb2_calls.h b/source4/libcli/smb2/smb2_calls.h index b6f8fdef71..6bee0dec91 100644 --- a/source4/libcli/smb2/smb2_calls.h +++ b/source4/libcli/smb2/smb2_calls.h @@ -52,138 +52,6 @@ struct smb2_negprot { } out; }; -struct smb2_session_setup { - struct { - /* static body buffer 16 (0x10) bytes */ - /* uint16_t buffer_code; 0x11 = 0x10 + 1 */ - uint16_t _pad; - uint32_t unknown2; /* 0xF */ - uint32_t unknown3; /* 0x00 */ - /* uint16_t secblob_ofs */ - /* uint16_t secblob_size */ - - /* dynamic body */ - DATA_BLOB secblob; - } in; - struct { - /* static body buffer 8 (0x08) bytes */ - /* uint16_t buffer_code; 0x09 = 0x08 +1 */ - uint16_t _pad; - /* uint16_t secblob_ofs */ - /* uint16_t secblob_size */ - - /* dynamic body */ - DATA_BLOB secblob; - - /* extracted from the SMB2 header */ - uint64_t uid; - } out; -}; - -struct smb2_tree_connect { - struct { - /* static body buffer 8 (0x08) bytes */ - /* uint16_t buffer_code; 0x09 = 0x08 + 1 */ - uint16_t unknown1; /* 0x0000 */ - /* uint16_t path_ofs */ - /* uint16_t path_size */ - - /* dynamic body */ - const char *path; /* as non-terminated UTF-16 on the wire */ - } in; - struct { - /* static body buffer 16 (0x10) bytes */ - /* uint16_t buffer_code; 0x10 */ - uint16_t unknown1; /* 0x02 */ - uint32_t unknown2; /* 0x00 */ - uint32_t unknown3; /* 0x00 */ - uint32_t access_mask; - - /* extracted from the SMB2 header */ - uint32_t tid; - } out; -}; - -#define SMB2_CREATE_FLAG_REQUEST_OPLOCK 0x0100 -#define SMB2_CREATE_FLAG_REQUEST_EXCLUSIVE_OPLOCK 0x0800 -#define SMB2_CREATE_FLAG_GRANT_OPLOCK 0x0001 -#define SMB2_CREATE_FLAG_GRANT_EXCLUSIVE_OPLOCK 0x0080 - -struct smb2_create { - struct { - /* static body buffer 56 (0x38) bytes */ - /* uint16_t buffer_code; 0x39 = 0x38 + 1 */ - uint16_t oplock_flags; /* SMB2_CREATE_FLAG_* */ - uint32_t impersonation; - uint32_t unknown3[4]; - uint32_t access_mask; - - uint32_t file_attr; - uint32_t share_access; - uint32_t open_disposition; - uint32_t create_options; - - /* uint16_t fname_ofs */ - /* uint16_t fname_size */ - /* uint32_t blob_ofs; */ - /* uint32_t blob_size; */ - - /* dynamic body */ - const char *fname; - - /* optional list of extended attributes */ - struct smb_ea_list eas; - } in; - - struct { - /* static body buffer 88 (0x58) bytes */ - /* uint16_t buffer_code; 0x59 = 0x58 + 1 */ - uint16_t oplock_flags; /* SMB2_CREATE_FLAG_* */ - uint32_t create_action; - NTTIME create_time; - NTTIME access_time; - NTTIME write_time; - NTTIME change_time; - uint64_t alloc_size; - uint64_t size; - uint32_t file_attr; - uint32_t _pad; - struct smb2_handle handle; - /* uint32_t blob_ofs; */ - /* uint32_t blob_size; */ - - /* dynamic body */ - DATA_BLOB blob; - } out; -}; - - -#define SMB2_CLOSE_FLAGS_FULL_INFORMATION (1<<0) - -struct smb2_close { - struct { - /* static body buffer 24 (0x18) bytes */ - /* uint16_t buffer_code; 0x18 */ - uint16_t flags; /* SMB2_CLOSE_FLAGS_* */ - uint32_t _pad; - struct smb2_handle handle; - } in; - - struct { - /* static body buffer 60 (0x3C) bytes */ - /* uint16_t buffer_code; 0x3C */ - uint16_t flags; - uint32_t _pad; - NTTIME create_time; - NTTIME access_time; - NTTIME write_time; - NTTIME change_time; - uint64_t alloc_size; - uint64_t size; - uint32_t file_attr; - } out; -}; - /* getinfo classes */ #define SMB2_GETINFO_FILE 0x01 #define SMB2_GETINFO_FS 0x02 @@ -230,139 +98,6 @@ struct smb2_setinfo { } in; }; -struct smb2_write { - struct { - /* static body buffer 48 (0x30) bytes */ - /* uint16_t buffer_code; 0x31 = 0x30 + 1 */ - /* uint16_t data_ofs; */ - /* uint32_t data_size; */ - uint64_t offset; - struct smb2_handle handle; - uint64_t unknown1; /* 0xFFFFFFFFFFFFFFFF */ - uint64_t unknown2; /* 0xFFFFFFFFFFFFFFFF */ - - /* dynamic body */ - DATA_BLOB data; - } in; - - struct { - /* static body buffer 17 (0x11) bytes */ - /* uint16_t buffer_code; 0x11 */ - uint16_t _pad; - uint32_t nwritten; - uint64_t unknown1; /* 0x0000000000000000 */ - uint8_t _bug; - } out; -}; - -struct smb2_read { - struct { - /* static body buffer 48 (0x30) bytes */ - /* uint16_t buffer_code; 0x31 = 0x30 + 1 */ - uint16_t _pad; - uint32_t length; - uint64_t offset; - struct smb2_handle handle; - uint64_t unknown1; /* 0x0000000000000000 */ - uint64_t unknown2; /* 0x0000000000000000 */ - uint8_t _bug; - } in; - - struct { - /* static body buffer 16 (0x10) bytes */ - /* uint16_t buffer_code; 0x11 = 0x10 + 1 */ - /* uint16_t data_ofs; */ - /* uint32_t data_size; */ - uint64_t unknown1; /* 0x0000000000000000 */ - - /* dynamic body */ - DATA_BLOB data; - } out; -}; - -/* - SMB2 uses different level numbers for the same old SMB search levels -*/ -#define SMB2_FIND_DIRECTORY_INFO 0x01 -#define SMB2_FIND_FULL_DIRECTORY_INFO 0x02 -#define SMB2_FIND_BOTH_DIRECTORY_INFO 0x03 -#define SMB2_FIND_NAME_INFO 0x0C -#define SMB2_FIND_ID_BOTH_DIRECTORY_INFO 0x25 -#define SMB2_FIND_ID_FULL_DIRECTORY_INFO 0x26 - -struct smb2_find { - struct { - /* static body buffer 32 (0x20) bytes */ - /* uint16_t buffer_code; 0x21 = 0x20 + 1 */ - uint8_t level; - uint8_t continue_flags; /* SMB2_CONTINUE_FLAG_* */ - uint32_t unknown; /* perhaps a continue token? */ - struct smb2_handle handle; - /* uint16_t pattern_ofs; */ - /* uint32_t pattern_size; */ - uint32_t max_response_size; - - /* dynamic body */ - const char *pattern; - } in; - - struct { - /* static body buffer 8 (0x08) bytes */ - /* uint16_t buffer_code; 0x08 */ - /* uint16_t blob_ofs; */ - /* uint32_t blob_size; */ - - /* dynamic body */ - DATA_BLOB blob; - } out; -}; - -struct smb2_ioctl { - struct { - /* static body buffer 56 (0x38) bytes */ - /* uint16_t buffer_code; 0x39 = 0x38 + 1 */ - uint16_t _pad; - uint32_t function; - struct smb2_handle handle; - /* uint32_t out_ofs; */ - /* uint32_t out_size; */ - uint32_t unknown2; - /* uint32_t in_ofs; */ - /* uint32_t in_size; */ - uint32_t max_response_size; - uint64_t flags; - - /* dynamic body */ - DATA_BLOB out; - DATA_BLOB in; - } in; - - struct { - /* static body buffer 48 (0x30) bytes */ - /* uint16_t buffer_code; 0x31 = 0x30 + 1 */ - uint16_t _pad; - uint32_t function; - struct smb2_handle handle; - /* uint32_t in_ofs; */ - /* uint32_t in_size; */ - /* uint32_t out_ofs; */ - /* uint32_t out_size; */ - uint32_t unknown2; - uint32_t unknown3; - - /* dynamic body */ - DATA_BLOB in; - DATA_BLOB out; - } out; -}; - -struct smb2_flush { - struct { - uint32_t unknown; - struct smb2_handle handle; - } in; -}; - struct cli_credentials; struct event_context; #include "libcli/smb2/smb2_proto.h" diff --git a/source4/libcli/smb2/write.c b/source4/libcli/smb2/write.c index 1edce3f773..760aadcd8e 100644 --- a/source4/libcli/smb2/write.c +++ b/source4/libcli/smb2/write.c @@ -42,7 +42,7 @@ struct smb2_request *smb2_write_send(struct smb2_tree *tree, struct smb2_write * } SBVAL(req->out.body, 0x08, io->in.offset); - smb2_push_handle(req->out.body+0x10, &io->in.handle); + smb2_push_handle(req->out.body+0x10, &io->in.file.handle); SBVAL(req->out.body, 0x20, io->in.unknown1); SBVAL(req->out.body, 0x28, io->in.unknown2); diff --git a/source4/libcli/smb_composite/sesssetup.c b/source4/libcli/smb_composite/sesssetup.c index 1b7756a3f4..0bad2ff1ad 100644 --- a/source4/libcli/smb_composite/sesssetup.c +++ b/source4/libcli/smb_composite/sesssetup.c @@ -165,6 +165,11 @@ static void request_handler(struct smbcli_request *req) state->req->async.private = c; return; } + break; + + case RAW_SESSSETUP_SMB2: + c->status = NT_STATUS_INTERNAL_ERROR; + break; } /* enforce the local signing required flag */ diff --git a/source4/librpc/rpc/dcerpc_smb2.c b/source4/librpc/rpc/dcerpc_smb2.c index 84ece71e4c..f3d6f9fe0e 100644 --- a/source4/librpc/rpc/dcerpc_smb2.c +++ b/source4/librpc/rpc/dcerpc_smb2.c @@ -103,12 +103,12 @@ static void smb2_read_callback(struct smb2_request *req) /* initiate another read request, as we only got part of a fragment */ ZERO_STRUCT(io); + io.in.file.handle = smb->handle; io.in.length = MIN(state->c->srv_max_xmit_frag, frag_length - state->data.length); if (io.in.length < 16) { io.in.length = 16; } - io.in.handle = smb->handle; req = smb2_read_send(smb->tree, &io); if (req == NULL) { @@ -147,7 +147,7 @@ static NTSTATUS send_read_request_continue(struct dcerpc_connection *c, DATA_BLO } ZERO_STRUCT(io); - io.in.handle = smb->handle; + io.in.file.handle = smb->handle; if (state->data.length >= 16) { uint16_t frag_length = dcerpc_get_frag_length(&state->data); @@ -232,11 +232,11 @@ static NTSTATUS smb2_send_trans_request(struct dcerpc_connection *c, DATA_BLOB * state->c = c; ZERO_STRUCT(io); - io.in.function = FSCTL_NAMED_PIPE_READ_WRITE; - io.in.handle = smb->handle; - io.in.max_response_size = 0x1000; - io.in.flags = 1; - io.in.out = *blob; + io.in.file.handle = smb->handle; + io.in.function = FSCTL_NAMED_PIPE_READ_WRITE; + io.in.max_response_size = 0x1000; + io.in.flags = 1; + io.in.out = *blob; req = smb2_ioctl_send(smb->tree, &io); if (req == NULL) { @@ -282,8 +282,8 @@ static NTSTATUS smb2_send_request(struct dcerpc_connection *c, DATA_BLOB *blob, } ZERO_STRUCT(io); - io.in.handle = smb->handle; - io.in.data = *blob; + io.in.file.handle = smb->handle; + io.in.data = *blob; req = smb2_write_send(smb->tree, &io); if (req == NULL) { @@ -309,7 +309,7 @@ static NTSTATUS smb2_shutdown_pipe(struct dcerpc_connection *c) if (!smb) return NT_STATUS_OK; ZERO_STRUCT(io); - io.in.handle = smb->handle; + io.in.file.handle = smb->handle; req = smb2_close_send(smb->tree, &io); if (req != NULL) { /* we don't care if this fails, so just free it if it succeeds */ @@ -454,7 +454,7 @@ static void pipe_open_recv(struct smb2_request *req) smb = talloc(c, struct smb2_private); if (composite_nomem(smb, ctx)) return; - smb->handle = io.out.handle; + smb->handle = io.out.file.handle; smb->tree = talloc_reference(smb, tree); smb->server_name= strupper_talloc(smb, tree->session->transport->socket->hostname); diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c index c669414e09..2b4f9bb8c5 100644 --- a/source4/ntvfs/cifs/vfs_cifs.c +++ b/source4/ntvfs/cifs/vfs_cifs.c @@ -714,6 +714,8 @@ static NTSTATUS cvfs_flush(struct ntvfs_module_context *ntvfs, case RAW_FLUSH_ALL: io->generic.in.file.fnum = 0xFFFF; break; + case RAW_FLUSH_SMB2: + return NT_STATUS_INVALID_LEVEL; } if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { diff --git a/source4/ntvfs/nbench/vfs_nbench.c b/source4/ntvfs/nbench/vfs_nbench.c index 2df3b95494..f7834a9751 100644 --- a/source4/ntvfs/nbench/vfs_nbench.c +++ b/source4/ntvfs/nbench/vfs_nbench.c @@ -566,6 +566,10 @@ static void nbench_flush_send(struct ntvfs_request *req) 0xFFFF, get_nt_error_c_code(req->async_states->status)); break; + default: + nbench_log(req, "Flush-%d - NOT HANDLED\n", + io->generic.level); + break; } PASS_THRU_REP_POST(req); diff --git a/source4/ntvfs/simple/vfs_simple.c b/source4/ntvfs/simple/vfs_simple.c index e0f0083630..9e5d4ae922 100644 --- a/source4/ntvfs/simple/vfs_simple.c +++ b/source4/ntvfs/simple/vfs_simple.c @@ -580,7 +580,9 @@ static NTSTATUS svfs_flush(struct ntvfs_module_context *ntvfs, switch (io->generic.level) { case RAW_FLUSH_FLUSH: - f = find_fd(private, io->flush.in.file.ntvfs); + case RAW_FLUSH_SMB2: + /* ignore the additional unknown option in SMB2 */ + f = find_fd(private, io->generic.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c index 0edee86a60..2256f51b73 100644 --- a/source4/smb_server/smb/sesssetup.c +++ b/source4/smb_server/smb/sesssetup.c @@ -373,6 +373,9 @@ NTSTATUS smbsrv_sesssetup_backend(struct smbsrv_request *req, case RAW_SESSSETUP_SPNEGO: status = sesssetup_spnego(req, sess); break; + case RAW_SESSSETUP_SMB2: + status = NT_STATUS_INTERNAL_ERROR; + break; } if (NT_STATUS_IS_OK(status)) { diff --git a/source4/smb_server/smb/trans2.c b/source4/smb_server/smb/trans2.c index 13b0cb41ac..6d56723d42 100644 --- a/source4/smb_server/smb/trans2.c +++ b/source4/smb_server/smb/trans2.c @@ -1085,6 +1085,7 @@ static BOOL find_fill_info(struct find_state *state, case RAW_SEARCH_FFIRST: case RAW_SEARCH_FUNIQUE: case RAW_SEARCH_GENERIC: + case RAW_SEARCH_SMB2: /* handled elsewhere */ return False; diff --git a/source4/torture/smb2/connect.c b/source4/torture/smb2/connect.c index 349fcda992..77b5d5c40d 100644 --- a/source4/torture/smb2/connect.c +++ b/source4/torture/smb2/connect.c @@ -38,8 +38,8 @@ static NTSTATUS torture_smb2_close(struct smb2_tree *tree, struct smb2_handle ha TALLOC_CTX *tmp_ctx = talloc_new(tree); ZERO_STRUCT(io); - io.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION; - io.in.handle = handle; + io.in.file.handle = handle; + io.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION; status = smb2_close(tree, &io); if (!NT_STATUS_IS_OK(status)) { printf("close failed - %s\n", nt_errstr(status)); @@ -85,8 +85,8 @@ static NTSTATUS torture_smb2_write(struct smb2_tree *tree, struct smb2_handle ha } ZERO_STRUCT(w); + w.in.file.handle = handle; w.in.offset = 0; - w.in.handle = handle; w.in.data = data; status = smb2_write(tree, &w); @@ -106,7 +106,7 @@ static NTSTATUS torture_smb2_write(struct smb2_tree *tree, struct smb2_handle ha torture_smb2_all_info(tree, handle); ZERO_STRUCT(f); - f.in.handle = handle; + f.in.file.handle = handle; status = smb2_flush(tree, &f); if (!NT_STATUS_IS_OK(status)) { @@ -115,9 +115,9 @@ static NTSTATUS torture_smb2_write(struct smb2_tree *tree, struct smb2_handle ha } ZERO_STRUCT(r); + r.in.file.handle = handle; r.in.length = data.length; r.in.offset = 0; - r.in.handle = handle; status = smb2_read(tree, tree, &r); if (!NT_STATUS_IS_OK(status)) { @@ -160,7 +160,7 @@ static struct smb2_handle torture_smb2_create(struct smb2_tree *tree, status = smb2_create(tree, tmp_ctx, &io); if (!NT_STATUS_IS_OK(status)) { printf("create1 failed - %s\n", nt_errstr(status)); - return io.out.handle; + return io.out.file.handle; } if (DEBUGLVL(1)) { @@ -175,13 +175,13 @@ static struct smb2_handle torture_smb2_create(struct smb2_tree *tree, printf("size = %lld\n", (long long)io.out.size); printf("file_attr = 0x%x\n", io.out.file_attr); printf("handle = %016llx%016llx\n", - (long long)io.out.handle.data[0], - (long long)io.out.handle.data[1]); + (long long)io.out.file.handle.data[0], + (long long)io.out.file.handle.data[1]); } talloc_free(tmp_ctx); - return io.out.handle; + return io.out.file.handle; } diff --git a/source4/torture/smb2/find.c b/source4/torture/smb2/find.c index 49b4030c07..2edcdc427c 100644 --- a/source4/torture/smb2/find.c +++ b/source4/torture/smb2/find.c @@ -121,10 +121,10 @@ static BOOL torture_smb2_find_levels(struct smb2_tree *tree) } ZERO_STRUCT(f); - f.in.handle = handle; - f.in.pattern = FNAME; - f.in.continue_flags = SMB2_CONTINUE_FLAG_RESTART; - f.in.max_response_size = 0x10000; + f.in.file.handle = handle; + f.in.pattern = FNAME; + f.in.continue_flags = SMB2_CONTINUE_FLAG_RESTART; + f.in.max_response_size = 0x10000; for (i=0;i<ARRAY_SIZE(levels);i++) { union smb_search_data *d; diff --git a/source4/torture/smb2/scan.c b/source4/torture/smb2/scan.c index 8e339c4080..a1eb2e80e0 100644 --- a/source4/torture/smb2/scan.c +++ b/source4/torture/smb2/scan.c @@ -171,15 +171,15 @@ BOOL torture_smb2_find_scan(struct torture_context *torture) } ZERO_STRUCT(io); - io.in.pattern = "*"; - io.in.continue_flags = SMB2_CONTINUE_FLAG_RESTART; - io.in.max_response_size = 0x10000; - io.in.handle = handle; + io.in.file.handle = handle; + io.in.pattern = "*"; + io.in.continue_flags = SMB2_CONTINUE_FLAG_RESTART; + io.in.max_response_size = 0x10000; for (i=1;i<0x100;i++) { io.in.level = i; - io.in.handle = handle; + io.in.file.handle = handle; status = smb2_find(tree, mem_ctx, &io); if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS) && !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER) && diff --git a/source4/torture/smb2/util.c b/source4/torture/smb2/util.c index 70be00f5fd..89c5488426 100644 --- a/source4/torture/smb2/util.c +++ b/source4/torture/smb2/util.c @@ -37,7 +37,7 @@ NTSTATUS smb2_util_close(struct smb2_tree *tree, struct smb2_handle h) struct smb2_close c; ZERO_STRUCT(c); - c.in.handle = h; + c.in.file.handle = h; return smb2_close(tree, &c); } @@ -67,7 +67,7 @@ NTSTATUS smb2_util_unlink(struct smb2_tree *tree, const char *fname) } NT_STATUS_NOT_OK_RETURN(status); - return smb2_util_close(tree, io.out.handle); + return smb2_util_close(tree, io.out.file.handle); } /* @@ -80,8 +80,8 @@ NTSTATUS smb2_util_write(struct smb2_tree *tree, struct smb2_write w; ZERO_STRUCT(w); + w.in.file.handle = handle; w.in.offset = offset; - w.in.handle = handle; w.in.data = data_blob_const(buf, size); return smb2_write(tree, &w); @@ -135,7 +135,7 @@ static NTSTATUS smb2_create_complex(struct smb2_tree *tree, const char *fname, talloc_free(tmp_ctx); NT_STATUS_NOT_OK_RETURN(status); - *handle = io.out.handle; + *handle = io.out.file.handle; if (!dir) { status = smb2_util_write(tree, *handle, buf, 0, sizeof(buf)); @@ -332,12 +332,12 @@ NTSTATUS torture_smb2_testfile(struct smb2_tree *tree, const char *fname, status = smb2_create(tree, tree, &io); NT_STATUS_NOT_OK_RETURN(status); - *handle = io.out.handle; + *handle = io.out.file.handle; ZERO_STRUCT(r); + r.in.file.handle = *handle; r.in.length = 5; r.in.offset = 0; - r.in.handle = *handle; smb2_read(tree, tree, &r); @@ -365,7 +365,7 @@ NTSTATUS torture_smb2_testdir(struct smb2_tree *tree, const char *fname, status = smb2_create(tree, tree, &io); NT_STATUS_NOT_OK_RETURN(status); - *handle = io.out.handle; + *handle = io.out.file.handle; return NT_STATUS_OK; } @@ -417,7 +417,7 @@ NTSTATUS smb2_util_roothandle(struct smb2_tree *tree, struct smb2_handle *handle status = smb2_create(tree, tree, &io); NT_STATUS_NOT_OK_RETURN(status); - *handle = io.out.handle; + *handle = io.out.file.handle; return NT_STATUS_OK; } |