#include <smbsrv/smb2_kproto.h>
#define SMB2_SHARE_CAP_CA SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY
#define ANON_OR_GUEST (SMB_USER_FLAG_ANON | SMB_USER_FLAG_GUEST)
smb_sdrc_t
smb2_tree_connect(smb_request_t *sr)
{
smb_arg_tcon_t *tcon = &sr->sr_tcon;
smb_tree_t *tree = NULL;
smb_sdrc_t rv = SDRC_SUCCESS;
uint16_t StructureSize;
uint16_t PathOffset;
uint16_t PathLength;
uint8_t ShareType;
uint32_t ShareFlags;
uint32_t Capabilities;
uint32_t status;
int skip;
int rc;
rc = smb_mbc_decodef(
&sr->smb_data, "w..ww",
&StructureSize,
&PathOffset,
&PathLength);
if (rc)
return (SDRC_ERROR);
skip = (PathOffset + sr->smb2_cmd_hdr) -
sr->smb_data.chain_offset;
if (skip < 0)
return (SDRC_ERROR);
if (skip > 0)
(void) smb_mbc_decodef(&sr->smb_data, "#.", skip);
rc = smb_mbc_decodef(
&sr->smb_data, "%#U",
sr, (uint_t)PathLength, &tcon->path);
if (rc)
return (SDRC_ERROR);
DTRACE_SMB2_START(op__TreeConnect, smb_request_t *, sr);
if (sr->session->dialect >= SMB_VERS_3_11 &&
(sr->uid_user->u_flags & ANON_OR_GUEST) == 0 &&
(sr->smb2_hdr_flags & SMB2_FLAGS_SIGNED) == 0 &&
sr->encrypted == B_FALSE) {
rv = SDRC_DROP_VC;
status = NT_STATUS_ACCESS_DENIED;
goto errout;
}
status = smb_tree_connect(sr);
errout:
sr->smb2_status = status;
DTRACE_SMB2_DONE(op__TreeConnect, smb_request_t *, sr);
if (status) {
(void) smb2sr_put_error(sr, status);
return (rv);
}
tree = sr->tid_tree;
switch (tree->t_res_type & STYPE_MASK) {
case STYPE_IPC:
ShareType = SMB2_SHARE_TYPE_PIPE;
break;
case STYPE_PRINTQ:
ShareType = SMB2_SHARE_TYPE_PRINT;
break;
case STYPE_DISKTREE:
default:
ShareType = SMB2_SHARE_TYPE_DISK;
break;
}
if (tree->t_encrypt != SMB_CONFIG_DISABLED)
ShareFlags = SMB2_SHAREFLAG_ENCRYPT_DATA;
else
ShareFlags = 0;
Capabilities = 0;
if ((tree->t_flags & SMB_TREE_DFSROOT) != 0)
Capabilities |= SMB2_SHARE_CAP_DFS;
if ((tree->t_flags & SMB_TREE_CA) != 0)
Capabilities |= SMB2_SHARE_CAP_CA;
(void) smb_mbc_encodef(
&sr->reply,
"wb.lll",
16,
ShareType,
ShareFlags,
Capabilities,
tree->t_access);
return (rv);
}