/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2017 Nexenta Systems, Inc. All rights reserved. * Copyright 2022 RackTop Systems, Inc. */ /* * Dispatch function for SMB2_TREE_CONNECT */ #include #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; /* * SMB2 Tree Connect request */ rc = smb_mbc_decodef( &sr->smb_data, "w..ww", &StructureSize, /* reserved */ &PathOffset, &PathLength); if (rc) return (SDRC_ERROR); /* * We're normally positioned at the path name now, * but there could be some padding before it. */ 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); /* * Get the path name */ 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 Connection.Dialect is "3.1.1" and Session.IsAnonymous and * Session.IsGuest are set to FALSE and the request is not signed * or encrypted, then the server MUST disconnect the connection. */ 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; } /* * [MS-SMB2] 3.3.5.7 Receiving an SMB2 TREE_CONNECT Request * * If RejectUnencryptedAccess is TRUE, * global EncryptData or Share.EncryptData is TRUE, * we support 3.x, and srv_cap doesn't indicate encryption support, * return ACCESS_DENIED. * * This also applies to SMB1, so do it in smb_tree_connect_core. */ 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; /* * Report the share type. */ 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; } /* * XXX These need work.. * See SMB1 flags in tcon->optional_support */ 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; /* * SMB2 Tree Connect reply */ (void) smb_mbc_encodef( &sr->reply, "wb.lll", 16, /* StructSize */ /* w */ ShareType, /* b */ ShareFlags, /* l */ Capabilities, /* l */ tree->t_access); /* l */ return (rv); }