Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-5844 want SMB2 ioctl FSCTL_SRV_COPYCHUNK
NEX-6124 smb_fsop_read/write should allow file != sr->fid_ofile
NEX-6125 smbtorture invalid response with smb2.ioctl
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-3553 SMB2/3 durable handles
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-5598 SMB needs a few more ioctls for Hyper-V
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-4159 SMB2 fsctl validate negotiate error
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-2188 Browsing top level share produces RPC error 1728
SMB-136 Snapshots not visible in Windows previous versions
NEX-1059 Shared folder is not available in Windows 7/8/2012 when SMB2 is enabled in Workgroup mode
(Implement "Secure Negotiation")
SMB-122 smbd core dumps in smbd_dc_update / smb_log
SMB-117 Win7 fails to open security properties
SMB-110 panic mapping a share from Nexentastor to the windows 2012 R2 client
SMB-109 Codenomicon: SMB TC: 409480 - Panic with SMB2_FIND request
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
*** 20,71 ****
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
! * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Dispatch function for SMB2_IOCTL
* [MS-SMB2] 3.3.5.15
*/
#include <smbsrv/smb2_kproto.h>
! #include <smbsrv/winioctl.h>
- struct smb2_ioctbl_ent {
- uint32_t te_code;
- uint32_t te_flags;
- uint32_t (*te_func)(smb_request_t *, smb_fsctl_t *);
- };
- static struct smb2_ioctbl_ent smb2_ioc_tbl[];
-
- /* te_flags */
- #define ITF_IPC_ONLY 1
- #define ITF_NO_FID 2
- #define ITF_DISK_FID 4
-
smb_sdrc_t
smb2_ioctl(smb_request_t *sr)
{
smb2fid_t smb2fid;
smb_fsctl_t fsctl;
mbuf_chain_t in_mbc;
- struct smb2_ioctbl_ent *te;
uint32_t InputOffset;
uint32_t MaxInputResp;
uint32_t OutputOffset;
uint32_t Flags;
- uint32_t status;
uint16_t StructSize;
int rc = 0;
bzero(&in_mbc, sizeof (in_mbc));
/*
! * SMB2 Ioctl request
*/
rc = smb_mbc_decodef(
&sr->smb_data, "w..lqqlllllll4.",
&StructSize, /* w */
/* reserved .. */
--- 20,60 ----
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
! * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Dispatch function for SMB2_IOCTL
* [MS-SMB2] 3.3.5.15
*/
#include <smbsrv/smb2_kproto.h>
! #include <smb/winioctl.h>
smb_sdrc_t
smb2_ioctl(smb_request_t *sr)
{
smb2fid_t smb2fid;
smb_fsctl_t fsctl;
mbuf_chain_t in_mbc;
uint32_t InputOffset;
uint32_t MaxInputResp;
uint32_t OutputOffset;
uint32_t Flags;
uint16_t StructSize;
+ uint16_t DeviceType;
+ uint32_t status = 0;
int rc = 0;
+ /* Todo: put fsctl in sr->arg.ioctl (visible in dtrace probes) */
bzero(&in_mbc, sizeof (in_mbc));
/*
! * Decode SMB2 Ioctl request
*/
rc = smb_mbc_decodef(
&sr->smb_data, "w..lqqlllllll4.",
&StructSize, /* w */
/* reserved .. */
*** 81,188 ****
&Flags); /* l */
/* reserved2 4. */
if (rc || StructSize != 57)
return (SDRC_ERROR);
! if (Flags != SMB2_0_IOCTL_IS_FSCTL) {
! status = NT_STATUS_NOT_SUPPORTED;
! goto errout;
}
-
- for (te = smb2_ioc_tbl; te->te_code; te++) {
- if (te->te_code == fsctl.CtlCode)
- break;
}
! if (te->te_code == 0) {
! #ifdef DEBUG
! cmn_err(CE_NOTE, "smb2_ioctl: unknown code 0x%x",
! fsctl.CtlCode);
! #endif
! status = NT_STATUS_NOT_SUPPORTED;
! goto errout;
! }
/*
! * Some requests are only valid on IPC$
*/
! if ((te->te_flags & ITF_IPC_ONLY) != 0 &&
! !STYPE_ISIPC(sr->tid_tree->t_res_type)) {
! status = NT_STATUS_INVALID_DEVICE_REQUEST;
! goto errout;
! }
/*
! * Note: some ioctl commands don't need a FID.
*/
! if (te->te_flags & ITF_NO_FID) {
! if (smb2fid.temporal != ~0LL) {
status = NT_STATUS_INVALID_PARAMETER;
- goto errout;
}
! } else {
status = smb2sr_lookup_fid(sr, &smb2fid);
if (status) {
status = NT_STATUS_FILE_CLOSED;
- goto errout;
}
}
/*
! * Note: some ioctls require a "disk" fid.
*/
! if (te->te_flags & ITF_DISK_FID) {
! if (sr->fid_ofile == NULL ||
! !SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) {
! status = NT_STATUS_INVALID_PARAMETER;
goto errout;
- }
- }
/*
! * If there's an input buffer, setup a shadow.
*/
! if (fsctl.InputCount) {
! if (InputOffset < (SMB2_HDR_SIZE + 56)) {
! status = NT_STATUS_INVALID_PARAMETER;
! goto errout;
}
- rc = MBC_SHADOW_CHAIN(&in_mbc, &sr->smb_data,
- sr->smb2_cmd_hdr + InputOffset, fsctl.InputCount);
- if (rc) {
- status = NT_STATUS_INVALID_PARAMETER;
- goto errout;
- }
- }
- fsctl.in_mbc = &in_mbc;
! /*
! * If output is possible, setup the output mbuf_chain
! */
! if (fsctl.MaxOutputResp > smb2_max_trans)
! fsctl.MaxOutputResp = smb2_max_trans;
! sr->raw_data.max_bytes = fsctl.MaxOutputResp;
! fsctl.out_mbc = &sr->raw_data;
/*
! * Dispatch to the handler for CtlCode
*/
! status = (te->te_func)(sr, &fsctl);
! if (status != 0) {
! sr->smb2_status = status;
! if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR)
! goto errout;
! /* Warnings like NT_STATUS_BUFFER_OVERFLOW are OK. */
}
fsctl.InputCount = 0;
InputOffset = SMB2_HDR_SIZE + 48;
fsctl.OutputCount = MBC_LENGTH(&sr->raw_data);
OutputOffset = (fsctl.OutputCount) ? InputOffset : 0;
/*
! * SMB2 Ioctl reply
*/
StructSize = 49;
rc = smb_mbc_encodef(
&sr->reply, "w..lqqlllll4.#C",
StructSize, /* w */
--- 70,195 ----
&Flags); /* l */
/* reserved2 4. */
if (rc || StructSize != 57)
return (SDRC_ERROR);
! /*
! * If there's an input buffer, setup a shadow.
! */
! if (fsctl.InputCount) {
! if (InputOffset < (SMB2_HDR_SIZE + 56))
! return (SDRC_ERROR);
! if (fsctl.InputCount > smb2_max_trans)
! return (SDRC_ERROR);
! rc = MBC_SHADOW_CHAIN(&in_mbc, &sr->smb_data,
! sr->smb2_cmd_hdr + InputOffset, fsctl.InputCount);
! if (rc) {
! return (SDRC_ERROR);
}
}
! fsctl.in_mbc = &in_mbc;
/*
! * If output is possible, setup the output mbuf_chain
*/
! if (fsctl.MaxOutputResp > smb2_max_trans)
! fsctl.MaxOutputResp = smb2_max_trans;
! sr->raw_data.max_bytes = fsctl.MaxOutputResp;
! fsctl.out_mbc = &sr->raw_data;
/*
! * [MS-SMB2] 3.3.5.15
! *
! * If the Flags field of the request is not SMB2_0_IOCTL_IS_FSCTL
! * the server MUST fail the request with STATUS_NOT_SUPPORTED.
! *
! * If the CtlCode is any of (... see switch below...) and the
! * value of FileId in the SMB2 Header of the request is not
! * 0xFFFFFFFFFFFFFFFF, then the server MUST fail the request
! * with STATUS_INVALID_PARAMETER. (Otherwise lookup the FID.)
*/
! if (Flags != SMB2_0_IOCTL_IS_FSCTL) {
! status = NT_STATUS_NOT_SUPPORTED;
! } else switch (fsctl.CtlCode) {
! case FSCTL_DFS_GET_REFERRALS:
! case FSCTL_DFS_GET_REFERRALS_EX:
! case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
! case FSCTL_VALIDATE_NEGOTIATE_INFO:
! case FSCTL_PIPE_WAIT:
! if (smb2fid.temporal != ~0LL ||
! smb2fid.persistent != ~0LL) {
status = NT_STATUS_INVALID_PARAMETER;
}
! break;
! default:
status = smb2sr_lookup_fid(sr, &smb2fid);
if (status) {
status = NT_STATUS_FILE_CLOSED;
}
+ break;
}
/*
! * Keep FID lookup before the start probe.
*/
! DTRACE_SMB2_START(op__Ioctl, smb_request_t *, sr);
!
! if (status)
goto errout;
/*
! * Dispatch to the handler for CtlCode
! * See CTL_CODE() in winioctl.h
*/
! DeviceType = fsctl.CtlCode >> 16;
! switch (DeviceType) {
! case FILE_DEVICE_DFS: /* 6 */
! status = smb_dfs_fsctl(sr, &fsctl);
! break;
! case FILE_DEVICE_FILE_SYSTEM: /* 9 */
! status = smb2_fsctl_fs(sr, &fsctl);
! break;
! case FILE_DEVICE_NAMED_PIPE: /* 17 */
! status = smb_opipe_fsctl(sr, &fsctl);
! break;
! case FILE_DEVICE_NETWORK_FILE_SYSTEM: /* 20 */
! status = smb2_fsctl_netfs(sr, &fsctl);
! break;
! default:
! status = NT_STATUS_NOT_SUPPORTED;
! break;
}
! errout:
! sr->smb2_status = status;
! DTRACE_SMB2_DONE(op__Ioctl, smb_request_t *, sr);
+ if (status != 0) {
/*
! * NT status codes with severity "error" normally cause
! * an error response with no data. However, there are
! * exceptions like smb2_fsctl_copychunk that may return
! * severity==error _with_ a data part.
*/
! if ((NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR) &&
! (fsctl.CtlCode != FSCTL_SRV_COPYCHUNK) &&
! (fsctl.CtlCode != FSCTL_SRV_COPYCHUNK_WRITE)) {
! /* no error data */
! smb2sr_put_error(sr, status);
! return (SDRC_SUCCESS);
}
+ /* Else, error response _with_ data. */
+ }
fsctl.InputCount = 0;
InputOffset = SMB2_HDR_SIZE + 48;
fsctl.OutputCount = MBC_LENGTH(&sr->raw_data);
OutputOffset = (fsctl.OutputCount) ? InputOffset : 0;
/*
! * Encode SMB2 Ioctl reply
*/
StructSize = 49;
rc = smb_mbc_encodef(
&sr->reply, "w..lqqlllll4.#C",
StructSize, /* w */
*** 192,264 ****
smb2fid.temporal, /* q */
InputOffset, /* l */
fsctl.InputCount, /* l */
OutputOffset, /* l */
fsctl.OutputCount, /* l */
! Flags, /* l */
/* reserved2 4. */
fsctl.OutputCount, /* # */
&sr->raw_data); /* C */
! return ((rc) ? SDRC_ERROR : SDRC_SUCCESS);
- errout:
- smb2sr_put_error(sr, status);
return (SDRC_SUCCESS);
}
-
- /* ARGSUSED */
- static uint32_t
- smb2_fsctl_notsup(smb_request_t *sr, smb_fsctl_t *fsctl)
- {
- return (NT_STATUS_NOT_SUPPORTED);
- }
-
- static struct smb2_ioctbl_ent
- smb2_ioc_tbl[] = {
-
- /*
- * FILE_DEVICE_DFS (6)
- */
- { FSCTL_DFS_GET_REFERRALS,
- ITF_IPC_ONLY | ITF_NO_FID, smb_dfs_get_referrals },
- { FSCTL_DFS_GET_REFERRALS_EX,
- ITF_IPC_ONLY | ITF_NO_FID, smb_dfs_get_referrals },
-
- /*
- * FILE_DEVICE_FILE_SYSTEM (9)
- */
- { FSCTL_SET_REPARSE_POINT, 0, smb2_fsctl_notsup },
- { FSCTL_CREATE_OR_GET_OBJECT_ID, 0, smb2_fsctl_notsup },
- { FSCTL_FILE_LEVEL_TRIM, 0, smb2_fsctl_notsup },
-
- /*
- * FILE_DEVICE_NAMED_PIPE (17)
- */
- { FSCTL_PIPE_PEEK,
- ITF_IPC_ONLY, smb_opipe_fsctl },
- { FSCTL_PIPE_TRANSCEIVE,
- ITF_IPC_ONLY, smb_opipe_fsctl },
- { FSCTL_PIPE_WAIT,
- ITF_IPC_ONLY | ITF_NO_FID, smb_opipe_fsctl },
-
- /*
- * FILE_DEVICE_NETWORK_FILE_SYSTEM (20)
- */
- { FSCTL_SRV_ENUMERATE_SNAPSHOTS,
- ITF_DISK_FID, smb_vss_enum_snapshots },
- { FSCTL_SRV_REQUEST_RESUME_KEY, 0, smb2_fsctl_notsup },
- { FSCTL_SRV_COPYCHUNK, 0, smb2_fsctl_notsup },
- { FSCTL_SRV_COPYCHUNK_WRITE, 0, smb2_fsctl_notsup },
- { FSCTL_SRV_READ_HASH, 0, smb2_fsctl_notsup },
-
- { FSCTL_LMR_REQUEST_RESILIENCY,
- ITF_NO_FID, smb2_fsctl_notsup },
- { FSCTL_QUERY_NETWORK_INTERFACE_INFO,
- ITF_NO_FID, smb2_fsctl_notsup },
- { FSCTL_VALIDATE_NEGOTIATE_INFO,
- ITF_NO_FID, smb2_fsctl_vneginfo },
-
- /*
- * End marker
- */
- { 0, 0, 0 }
- };
--- 199,212 ----
smb2fid.temporal, /* q */
InputOffset, /* l */
fsctl.InputCount, /* l */
OutputOffset, /* l */
fsctl.OutputCount, /* l */
! 0, /* Flags l */
/* reserved2 4. */
fsctl.OutputCount, /* # */
&sr->raw_data); /* C */
! if (rc)
! sr->smb2_status = NT_STATUS_INTERNAL_ERROR;
return (SDRC_SUCCESS);
}