xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb2_negotiate.c (revision b0bb0d63258be430b0e22afcb1581974bd7b568e)
1a90cf9f2SGordon Ross /*
2a90cf9f2SGordon Ross  * This file and its contents are supplied under the terms of the
3a90cf9f2SGordon Ross  * Common Development and Distribution License ("CDDL"), version 1.0.
4a90cf9f2SGordon Ross  * You may only use this file in accordance with the terms of version
5a90cf9f2SGordon Ross  * 1.0 of the CDDL.
6a90cf9f2SGordon Ross  *
7a90cf9f2SGordon Ross  * A full copy of the text of the CDDL should have accompanied this
8a90cf9f2SGordon Ross  * source.  A copy of the CDDL is also available via the Internet at
9a90cf9f2SGordon Ross  * http://www.illumos.org/license/CDDL.
10a90cf9f2SGordon Ross  */
11a90cf9f2SGordon Ross 
12a90cf9f2SGordon Ross /*
134ad35fa3SMatt Barden  * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
14b716e3d0SGordon Ross  * Copyright 2022 RackTop Systems, Inc.
15a90cf9f2SGordon Ross  */
16a90cf9f2SGordon Ross 
17a90cf9f2SGordon Ross /*
18a90cf9f2SGordon Ross  * Dispatch function for SMB2_NEGOTIATE
19a90cf9f2SGordon Ross  */
20a90cf9f2SGordon Ross 
21a90cf9f2SGordon Ross #include <smbsrv/smb2_kproto.h>
22a90cf9f2SGordon Ross #include <smbsrv/smb2.h>
234e065a9fSAlexander Stetsenko #include <sys/random.h>
24ebc5aadbSAndrew Stormont 
25b716e3d0SGordon Ross /*
26b716e3d0SGordon Ross  * Note from [MS-SMB2] Sec. 2.2.3:  Windows servers return
27b716e3d0SGordon Ross  * invalid parameter if the dialect count is greater than 64
28b716e3d0SGordon Ross  * This is here (and not in smb2.h) because this is technically
29b716e3d0SGordon Ross  * an implementation detail, not protocol specification.
30b716e3d0SGordon Ross  */
31b716e3d0SGordon Ross #define	SMB2_NEGOTIATE_MAX_DIALECTS	64
32b716e3d0SGordon Ross 
33a90cf9f2SGordon Ross static int smb2_negotiate_common(smb_request_t *, uint16_t);
34a90cf9f2SGordon Ross 
35700daa96SAndrew Stormont /* List of supported capabilities.  Can be patched for testing. */
36a90cf9f2SGordon Ross uint32_t smb2srv_capabilities =
37a90cf9f2SGordon Ross 	SMB2_CAP_DFS |
3894047d49SGordon Ross 	SMB2_CAP_LEASING |
391160dcf7SMatt Barden 	SMB2_CAP_LARGE_MTU |
408d94f651SGordon Ross 	SMB2_CAP_PERSISTENT_HANDLES |
415501be74SGordon Ross #ifndef	_FAKE_KERNEL
425501be74SGordon Ross 	SMB2_CAP_ENCRYPTION |
435501be74SGordon Ross #endif
445501be74SGordon Ross 	0;
45a90cf9f2SGordon Ross 
468d94f651SGordon Ross /* These are the only capabilities defined for SMB2.X */
478d94f651SGordon Ross #define	SMB_2X_CAPS (SMB2_CAP_DFS | SMB2_CAP_LEASING | SMB2_CAP_LARGE_MTU)
488d94f651SGordon Ross 
49a90cf9f2SGordon Ross /*
50a90cf9f2SGordon Ross  * These are not intended as customer tunables, but dev. & test folks
51a90cf9f2SGordon Ross  * might want to adjust them (with caution).
52a90cf9f2SGordon Ross  *
53a90cf9f2SGordon Ross  * smb2_tcp_bufsize is the TCP buffer size, applied to the network socket
54a90cf9f2SGordon Ross  * with setsockopt SO_SNDBUF, SO_RCVBUF.  These set the TCP window size.
55a90cf9f2SGordon Ross  * This is also used as a "sanity limit" for internal send/reply message
56a90cf9f2SGordon Ross  * allocations.  Note that with compounding SMB2 messages may contain
57a90cf9f2SGordon Ross  * multiple requests/responses.  This size should be large enough for
58a90cf9f2SGordon Ross  * at least a few SMB2 requests, and at least 2X smb2_max_rwsize.
59a90cf9f2SGordon Ross  *
60a90cf9f2SGordon Ross  * smb2_max_rwsize is what we put in the SMB2 negotiate response to tell
61a90cf9f2SGordon Ross  * the client the largest read and write request size we'll support.
6287ca5dcaSGordon Ross  * For now, we're using contiguous allocations, so keep this at 64KB
6387ca5dcaSGordon Ross  * so that (even with message overhead) allocations stay below 128KB,
6487ca5dcaSGordon Ross  * avoiding kmem_alloc -> page_create_va thrashing.
65a90cf9f2SGordon Ross  *
66a90cf9f2SGordon Ross  * smb2_max_trans is the largest "transact" send or receive, which is
67a90cf9f2SGordon Ross  * used for directory listings and info set/get operations.
68a90cf9f2SGordon Ross  */
69a90cf9f2SGordon Ross uint32_t smb2_tcp_bufsize = (1<<22);	/* 4MB */
7087ca5dcaSGordon Ross uint32_t smb2_max_rwsize = (1<<16);	/* 64KB */
71a90cf9f2SGordon Ross uint32_t smb2_max_trans  = (1<<16);	/* 64KB */
72a90cf9f2SGordon Ross 
73a90cf9f2SGordon Ross /*
74aa321b3cSDan McDonald  * With clients (e.g. HP scanners) that don't advertise SMB2_CAP_LARGE_MTU
75aa321b3cSDan McDonald  * (including all clients using dialect < SMB 2.1), use a "conservative" value
76aa321b3cSDan McDonald  * for max r/w size because some older clients misbehave with larger values.
77aa321b3cSDan McDonald  * 64KB is recommended in the [MS-SMB2] spec.  (3.3.5.3.1 SMB 2.1 or SMB 3.x
78aa321b3cSDan McDonald  * Support) as the minimum so we'll use that.
79aa321b3cSDan McDonald  */
80aa321b3cSDan McDonald uint32_t smb2_old_rwsize = (1<<16);	/* 64KB */
81aa321b3cSDan McDonald 
82aa321b3cSDan McDonald /*
83a90cf9f2SGordon Ross  * List of all SMB2 versions we implement.  Note that the
843e2c0c09SMatt Barden  * versions we support may be limited by the
853e2c0c09SMatt Barden  * _cfg.skc_max_protocol and min_protocol settings.
86a90cf9f2SGordon Ross  */
87a90cf9f2SGordon Ross static uint16_t smb2_versions[] = {
88a90cf9f2SGordon Ross 	0x202,	/* SMB 2.002 */
89a90cf9f2SGordon Ross 	0x210,	/* SMB 2.1 */
90c51c88bdSMatt Barden 	0x300,	/* SMB 3.0 */
91dfa42fabSMatt Barden 	0x302,	/* SMB 3.02 */
924e065a9fSAlexander Stetsenko 	0x311,	/* SMB 3.11 */
93a90cf9f2SGordon Ross };
94a90cf9f2SGordon Ross static uint16_t smb2_nversions =
95a90cf9f2SGordon Ross     sizeof (smb2_versions) / sizeof (smb2_versions[0]);
96a90cf9f2SGordon Ross 
974e065a9fSAlexander Stetsenko enum smb2_neg_ctx_type {
984e065a9fSAlexander Stetsenko 	SMB2_PREAUTH_INTEGRITY_CAPS		= 1,
994e065a9fSAlexander Stetsenko 	SMB2_ENCRYPTION_CAPS			= 2,
1004e065a9fSAlexander Stetsenko 	SMB2_COMPRESSION_CAPS			= 3,	/* not imlemented */
1014e065a9fSAlexander Stetsenko 	SMB2_NETNAME_NEGOTIATE_CONTEXT_ID	= 5	/* not imlemented */
1024e065a9fSAlexander Stetsenko };
1034e065a9fSAlexander Stetsenko 
1044e065a9fSAlexander Stetsenko typedef struct smb2_negotiate_ctx {
1054e065a9fSAlexander Stetsenko 	uint16_t	type;
1064e065a9fSAlexander Stetsenko 	uint16_t	datalen;
1074e065a9fSAlexander Stetsenko } smb2_neg_ctx_t;
1084e065a9fSAlexander Stetsenko 
1094e065a9fSAlexander Stetsenko #define	SMB31_PREAUTH_CTX_SALT_LEN	32
1104e065a9fSAlexander Stetsenko 
1114e065a9fSAlexander Stetsenko /*
11274e3b2c7SAndy Fiddaman  * SMB 3.1.1 originally specified a single hashing algorithm - SHA-512 - and
1134e065a9fSAlexander Stetsenko  * two encryption ones - AES-128-CCM and AES-128-GCM.
11474e3b2c7SAndy Fiddaman  * Windows Server 2022 and Windows 11 introduced two further encryption
11574e3b2c7SAndy Fiddaman  * algorithms - AES-256-CCM and AES-256-GCM.
1164e065a9fSAlexander Stetsenko  */
1174e065a9fSAlexander Stetsenko #define	MAX_HASHID_NUM	(1)
11874e3b2c7SAndy Fiddaman #define	MAX_CIPHER_NUM	(4)
1194e065a9fSAlexander Stetsenko 
1204e065a9fSAlexander Stetsenko typedef struct smb2_preauth_integrity_caps {
1214e065a9fSAlexander Stetsenko 	uint16_t	picap_hash_count;
1224e065a9fSAlexander Stetsenko 	uint16_t	picap_salt_len;
1234e065a9fSAlexander Stetsenko 	uint16_t	picap_hash_id;
1244e065a9fSAlexander Stetsenko 	uint8_t		picap_salt[SMB31_PREAUTH_CTX_SALT_LEN];
1254e065a9fSAlexander Stetsenko } smb2_preauth_caps_t;
1264e065a9fSAlexander Stetsenko 
1274e065a9fSAlexander Stetsenko typedef struct smb2_encryption_caps {
1284e065a9fSAlexander Stetsenko 	uint16_t	encap_cipher_count;
1294e065a9fSAlexander Stetsenko 	uint16_t	encap_cipher_ids[MAX_CIPHER_NUM];
1304e065a9fSAlexander Stetsenko } smb2_encrypt_caps_t;
1314e065a9fSAlexander Stetsenko 
1324e065a9fSAlexander Stetsenko /*
1334e065a9fSAlexander Stetsenko  * The contexts we support
1344e065a9fSAlexander Stetsenko  */
1354e065a9fSAlexander Stetsenko typedef struct smb2_preauth_neg_ctx {
1364e065a9fSAlexander Stetsenko 	smb2_neg_ctx_t		neg_ctx;
1374e065a9fSAlexander Stetsenko 	smb2_preauth_caps_t	preauth_caps;
1384e065a9fSAlexander Stetsenko } smb2_preauth_neg_ctx_t;
1394e065a9fSAlexander Stetsenko 
1404e065a9fSAlexander Stetsenko typedef struct smb2_encrypt_neg_ctx {
1414e065a9fSAlexander Stetsenko 	smb2_neg_ctx_t		neg_ctx;
1424e065a9fSAlexander Stetsenko 	smb2_encrypt_caps_t	encrypt_caps;
1434e065a9fSAlexander Stetsenko } smb2_encrypt_neg_ctx_t;
1444e065a9fSAlexander Stetsenko 
1454e065a9fSAlexander Stetsenko typedef struct smb2_neg_ctxs {
1464e065a9fSAlexander Stetsenko 	uint32_t		offset;
1474e065a9fSAlexander Stetsenko 	uint16_t		count;
1484e065a9fSAlexander Stetsenko 	smb2_preauth_neg_ctx_t	preauth_ctx;
1494e065a9fSAlexander Stetsenko 	smb2_encrypt_neg_ctx_t	encrypt_ctx;
1504e065a9fSAlexander Stetsenko } smb2_neg_ctxs_t;
1514e065a9fSAlexander Stetsenko 
1524e065a9fSAlexander Stetsenko #define	NEG_CTX_INFO_OFFSET	(SMB2_HDR_SIZE + 28)
1534e065a9fSAlexander Stetsenko #define	NEG_CTX_OFFSET_OFFSET	(SMB2_HDR_SIZE + 64)
1544e065a9fSAlexander Stetsenko #define	NEG_CTX_MAX_COUNT	(16)
1554e065a9fSAlexander Stetsenko #define	NEG_CTX_MAX_DATALEN	(256)
1564e065a9fSAlexander Stetsenko 
1574e065a9fSAlexander Stetsenko #define	STATUS_SMB_NO_PREAUTH_INEGRITY_HASH_OVERLAP	(0xC05D0000)
1584e065a9fSAlexander Stetsenko 
1594e065a9fSAlexander Stetsenko #define	STATUS_PREAUTH_HASH_OVERLAP \
1604e065a9fSAlexander Stetsenko     STATUS_SMB_NO_PREAUTH_INEGRITY_HASH_OVERLAP
1614e065a9fSAlexander Stetsenko 
162dee7ba86SAlexander Stetsenko #define	SMB3_CIPHER_ENABLED(c, f)	((c) <= SMB3_CIPHER_MAX && \
163dee7ba86SAlexander Stetsenko     SMB3_CIPHER_BIT(c) & (f))
164dee7ba86SAlexander Stetsenko 
165b716e3d0SGordon Ross typedef struct smb2_arg_negotiate {
166b716e3d0SGordon Ross 	struct smb2_neg_ctxs	neg_in_ctxs;
167b716e3d0SGordon Ross 	struct smb2_neg_ctxs	neg_out_ctxs;
168b716e3d0SGordon Ross 	uint16_t		neg_dialect_cnt;
169b716e3d0SGordon Ross 	uint16_t		neg_dialects[SMB2_NEGOTIATE_MAX_DIALECTS];
170b716e3d0SGordon Ross 	uint16_t		neg_highest_dialect;
171b716e3d0SGordon Ross } smb2_arg_negotiate_t;
172b716e3d0SGordon Ross 
173b716e3d0SGordon Ross 
174b716e3d0SGordon Ross static boolean_t
175b716e3d0SGordon Ross smb2_supported_version(smb_session_t *s, uint16_t version)
176b716e3d0SGordon Ross {
177b716e3d0SGordon Ross 	int i;
178b716e3d0SGordon Ross 
179b716e3d0SGordon Ross 	if (version > s->s_cfg.skc_max_protocol ||
180b716e3d0SGordon Ross 	    version < s->s_cfg.skc_min_protocol)
181b716e3d0SGordon Ross 		return (B_FALSE);
182b716e3d0SGordon Ross 	for (i = 0; i < smb2_nversions; i++)
183b716e3d0SGordon Ross 		if (version == smb2_versions[i])
184b716e3d0SGordon Ross 			return (B_TRUE);
185b716e3d0SGordon Ross 	return (B_FALSE);
186b716e3d0SGordon Ross }
187b716e3d0SGordon Ross 
188b716e3d0SGordon Ross static uint16_t
189b716e3d0SGordon Ross smb2_find_best_dialect(smb_session_t *s, uint16_t cl_versions[],
190b716e3d0SGordon Ross     uint16_t version_cnt)
191b716e3d0SGordon Ross {
192b716e3d0SGordon Ross 	uint16_t best_version = 0;
193b716e3d0SGordon Ross 	int i;
194b716e3d0SGordon Ross 
195b716e3d0SGordon Ross 	for (i = 0; i < version_cnt; i++)
196b716e3d0SGordon Ross 		if (smb2_supported_version(s, cl_versions[i]) &&
197b716e3d0SGordon Ross 		    best_version < cl_versions[i])
198b716e3d0SGordon Ross 			best_version = cl_versions[i];
199b716e3d0SGordon Ross 
200b716e3d0SGordon Ross 	return (best_version);
201b716e3d0SGordon Ross }
202b716e3d0SGordon Ross 
2034e065a9fSAlexander Stetsenko /*
2044e065a9fSAlexander Stetsenko  * This function should be called only for dialect >= 0x311
2054e065a9fSAlexander Stetsenko  * Negotiate context list should contain exactly one
2064e065a9fSAlexander Stetsenko  * SMB2_PREAUTH_INTEGRITY_CAPS context.
2074e065a9fSAlexander Stetsenko  * Otherwise STATUS_INVALID_PARAMETER.
2084e065a9fSAlexander Stetsenko  * It should contain at least 1 hash algorith what server does support.
2094e065a9fSAlexander Stetsenko  * Otehrwise STATUS_SMB_NO_PREAUTH_INEGRITY_HASH_OVERLAP.
2104e065a9fSAlexander Stetsenko  */
2114e065a9fSAlexander Stetsenko static uint32_t
212b716e3d0SGordon Ross smb31_decode_neg_ctxs(smb_request_t *sr)
2134e065a9fSAlexander Stetsenko {
2144e065a9fSAlexander Stetsenko 	smb_session_t *s = sr->session;
215b716e3d0SGordon Ross 	smb2_arg_negotiate_t *nego = sr->arg.other;
216b716e3d0SGordon Ross 	smb2_neg_ctxs_t *neg_ctxs = &nego->neg_in_ctxs;
2174e065a9fSAlexander Stetsenko 	smb2_preauth_caps_t *picap = &neg_ctxs->preauth_ctx.preauth_caps;
2184e065a9fSAlexander Stetsenko 	smb2_encrypt_caps_t *encap = &neg_ctxs->encrypt_ctx.encrypt_caps;
219dee7ba86SAlexander Stetsenko 	boolean_t found_sha512 = B_FALSE;
220dee7ba86SAlexander Stetsenko 	boolean_t found_cipher = B_FALSE;
221*b0bb0d63SGordon Ross 	uint32_t ciphers = sr->sr_server->sv_cfg.skc_encrypt_ciphers;
2224e065a9fSAlexander Stetsenko 	uint32_t status = 0;
2234e065a9fSAlexander Stetsenko 	int32_t skip;
2244e065a9fSAlexander Stetsenko 	int found_preauth_ctx = 0;
2254e065a9fSAlexander Stetsenko 	int found_encrypt_ctx = 0;
2264e065a9fSAlexander Stetsenko 	int cnt, i;
2274e065a9fSAlexander Stetsenko 	int rc;
2284e065a9fSAlexander Stetsenko 
2294e065a9fSAlexander Stetsenko 	/*
2304e065a9fSAlexander Stetsenko 	 * There should be exactly 1 SMB2_PREAUTH_INTEGRITY_CAPS negotiate ctx.
2314e065a9fSAlexander Stetsenko 	 * SMB2_ENCRYPTION_CAPS is optional one.
2324e065a9fSAlexander Stetsenko 	 * If there is no contexts or there are to many then stop parsing.
2334e065a9fSAlexander Stetsenko 	 */
2344e065a9fSAlexander Stetsenko 	cnt = neg_ctxs->count;
2354e065a9fSAlexander Stetsenko 	if (cnt < 1 || cnt > NEG_CTX_MAX_COUNT) {
2364e065a9fSAlexander Stetsenko 		status = NT_STATUS_INVALID_PARAMETER;
2374e065a9fSAlexander Stetsenko 		goto errout;
2384e065a9fSAlexander Stetsenko 	}
2394e065a9fSAlexander Stetsenko 
2404e065a9fSAlexander Stetsenko 	/*
2414e065a9fSAlexander Stetsenko 	 * Cannot proceed parsing if the first context isn't aligned by 8.
2424e065a9fSAlexander Stetsenko 	 */
2434e065a9fSAlexander Stetsenko 	if (neg_ctxs->offset % 8 != 0) {
2444e065a9fSAlexander Stetsenko 		status = NT_STATUS_INVALID_PARAMETER;
2454e065a9fSAlexander Stetsenko 		goto errout;
2464e065a9fSAlexander Stetsenko 	}
2474e065a9fSAlexander Stetsenko 
2484e065a9fSAlexander Stetsenko 	if ((skip = neg_ctxs->offset - sr->command.chain_offset) != 0 &&
2494e065a9fSAlexander Stetsenko 	    smb_mbc_decodef(&sr->command, "#.", skip) != 0) {
2504e065a9fSAlexander Stetsenko 		status = NT_STATUS_INVALID_PARAMETER;
2514e065a9fSAlexander Stetsenko 		goto errout;
2524e065a9fSAlexander Stetsenko 	}
2534e065a9fSAlexander Stetsenko 
2544e065a9fSAlexander Stetsenko 	/*
2554e065a9fSAlexander Stetsenko 	 * Parse negotiate contexts. Ignore non-decoding errors to fill
2564e065a9fSAlexander Stetsenko 	 * as much as possible data for dtrace probe.
2574e065a9fSAlexander Stetsenko 	 */
2584e065a9fSAlexander Stetsenko 	for (i = 0; i < cnt; i++) {
2594e065a9fSAlexander Stetsenko 		smb2_neg_ctx_t neg_ctx;
2604e065a9fSAlexander Stetsenko 		int32_t ctx_end_off;
2614e065a9fSAlexander Stetsenko 		int32_t ctx_next_off;
2624e065a9fSAlexander Stetsenko 
2634e065a9fSAlexander Stetsenko 		if (i > 0) {
2644e065a9fSAlexander Stetsenko 			if ((skip = ctx_next_off - ctx_end_off) != 0 &&
2654e065a9fSAlexander Stetsenko 			    smb_mbc_decodef(&sr->command, "#.", skip) != 0) {
2664e065a9fSAlexander Stetsenko 				status = NT_STATUS_INVALID_PARAMETER;
2674e065a9fSAlexander Stetsenko 				goto errout;
2684e065a9fSAlexander Stetsenko 			}
2694e065a9fSAlexander Stetsenko 		}
2704e065a9fSAlexander Stetsenko 
2714e065a9fSAlexander Stetsenko 		rc = smb_mbc_decodef(
2724e065a9fSAlexander Stetsenko 		    &sr->command, "ww4.",
2734e065a9fSAlexander Stetsenko 		    &neg_ctx.type,	/* w */
2744e065a9fSAlexander Stetsenko 		    &neg_ctx.datalen);	/* w */
2754e065a9fSAlexander Stetsenko 		if (rc != 0) {
2764e065a9fSAlexander Stetsenko 			status = NT_STATUS_INVALID_PARAMETER;
2774e065a9fSAlexander Stetsenko 			goto errout;
2784e065a9fSAlexander Stetsenko 		}
2794e065a9fSAlexander Stetsenko 
2804e065a9fSAlexander Stetsenko 		/*
2814e065a9fSAlexander Stetsenko 		 * We got something crazy
2824e065a9fSAlexander Stetsenko 		 */
2834e065a9fSAlexander Stetsenko 		if (neg_ctx.datalen > NEG_CTX_MAX_DATALEN) {
2844e065a9fSAlexander Stetsenko 			status = NT_STATUS_INVALID_PARAMETER;
2854e065a9fSAlexander Stetsenko 			goto errout;
2864e065a9fSAlexander Stetsenko 		}
2874e065a9fSAlexander Stetsenko 
2884e065a9fSAlexander Stetsenko 		ctx_end_off = sr->command.chain_offset + neg_ctx.datalen;
2894e065a9fSAlexander Stetsenko 		ctx_next_off = P2ROUNDUP(ctx_end_off, 8);
2904e065a9fSAlexander Stetsenko 
2914e065a9fSAlexander Stetsenko 		switch (neg_ctx.type) {
2924e065a9fSAlexander Stetsenko 		case SMB2_PREAUTH_INTEGRITY_CAPS:
2934e065a9fSAlexander Stetsenko 			memcpy(&neg_ctxs->preauth_ctx.neg_ctx, &neg_ctx,
2944e065a9fSAlexander Stetsenko 			    sizeof (neg_ctx));
2954e065a9fSAlexander Stetsenko 
2964e065a9fSAlexander Stetsenko 			if (found_preauth_ctx++ != 0) {
2974e065a9fSAlexander Stetsenko 				status = NT_STATUS_INVALID_PARAMETER;
2984e065a9fSAlexander Stetsenko 				continue;
2994e065a9fSAlexander Stetsenko 			}
3004e065a9fSAlexander Stetsenko 
3014e065a9fSAlexander Stetsenko 			rc = smb_mbc_decodef(
3024e065a9fSAlexander Stetsenko 			    &sr->command, "ww",
3034e065a9fSAlexander Stetsenko 			    &picap->picap_hash_count,	/* w */
3044e065a9fSAlexander Stetsenko 			    &picap->picap_salt_len);	/* w */
3054e065a9fSAlexander Stetsenko 			if (rc != 0 || picap->picap_hash_count >
3064e065a9fSAlexander Stetsenko 			    MAX_HASHID_NUM) {
3074e065a9fSAlexander Stetsenko 				status = NT_STATUS_INVALID_PARAMETER;
3084e065a9fSAlexander Stetsenko 				goto errout;
3094e065a9fSAlexander Stetsenko 			}
3104e065a9fSAlexander Stetsenko 
3114e065a9fSAlexander Stetsenko 			/*
3124e065a9fSAlexander Stetsenko 			 * Get hash id
3134e065a9fSAlexander Stetsenko 			 */
3144e065a9fSAlexander Stetsenko 			rc = smb_mbc_decodef(
3154e065a9fSAlexander Stetsenko 			    &sr->command, "#w",
3164e065a9fSAlexander Stetsenko 			    picap->picap_hash_count,
3174e065a9fSAlexander Stetsenko 			    &picap->picap_hash_id);	/* w */
3184e065a9fSAlexander Stetsenko 			if (rc != 0) {
3194e065a9fSAlexander Stetsenko 				status = NT_STATUS_INVALID_PARAMETER;
3204e065a9fSAlexander Stetsenko 				goto errout;
3214e065a9fSAlexander Stetsenko 			}
3224e065a9fSAlexander Stetsenko 
3234e065a9fSAlexander Stetsenko 			/*
3244e065a9fSAlexander Stetsenko 			 * Get salt
3254e065a9fSAlexander Stetsenko 			 */
3264e065a9fSAlexander Stetsenko 			rc = smb_mbc_decodef(
3274e065a9fSAlexander Stetsenko 			    &sr->command, "#c",
3284e065a9fSAlexander Stetsenko 			    sizeof (picap->picap_salt),
3294e065a9fSAlexander Stetsenko 			    &picap->picap_salt[0]);	/* w */
3304e065a9fSAlexander Stetsenko 			if (rc != 0) {
3314e065a9fSAlexander Stetsenko 				status = NT_STATUS_INVALID_PARAMETER;
3324e065a9fSAlexander Stetsenko 				goto errout;
3334e065a9fSAlexander Stetsenko 			}
3344e065a9fSAlexander Stetsenko 
3354e065a9fSAlexander Stetsenko 			/*
3364e065a9fSAlexander Stetsenko 			 * In SMB 0x311 there should be exactly 1 preauth
3374e065a9fSAlexander Stetsenko 			 * negotiate context, and there should be exactly 1
3384e065a9fSAlexander Stetsenko 			 * hash value in the list - SHA512.
3394e065a9fSAlexander Stetsenko 			 */
3404e065a9fSAlexander Stetsenko 			if (picap->picap_hash_count != 1) {
3414e065a9fSAlexander Stetsenko 				status = NT_STATUS_INVALID_PARAMETER;
3424e065a9fSAlexander Stetsenko 				continue;
3434e065a9fSAlexander Stetsenko 			}
3444e065a9fSAlexander Stetsenko 
3454e065a9fSAlexander Stetsenko 			if (picap->picap_hash_id == SMB3_HASH_SHA512)
346dee7ba86SAlexander Stetsenko 				found_sha512 = B_TRUE;
3474e065a9fSAlexander Stetsenko 			break;
3484e065a9fSAlexander Stetsenko 		case SMB2_ENCRYPTION_CAPS:
3494e065a9fSAlexander Stetsenko 			memcpy(&neg_ctxs->preauth_ctx.neg_ctx, &neg_ctx,
3504e065a9fSAlexander Stetsenko 			    sizeof (neg_ctx));
3514e065a9fSAlexander Stetsenko 
3524e065a9fSAlexander Stetsenko 			if (found_encrypt_ctx++ != 0) {
3534e065a9fSAlexander Stetsenko 				status = NT_STATUS_INVALID_PARAMETER;
3544e065a9fSAlexander Stetsenko 				continue;
3554e065a9fSAlexander Stetsenko 			}
3564e065a9fSAlexander Stetsenko 
3574e065a9fSAlexander Stetsenko 			rc = smb_mbc_decodef(
3584e065a9fSAlexander Stetsenko 			    &sr->command, "w",
3594e065a9fSAlexander Stetsenko 			    &encap->encap_cipher_count);	/* w */
3604e065a9fSAlexander Stetsenko 			if (rc != 0 || encap->encap_cipher_count >
3614e065a9fSAlexander Stetsenko 			    MAX_CIPHER_NUM) {
3624e065a9fSAlexander Stetsenko 				status = NT_STATUS_INVALID_PARAMETER;
3634e065a9fSAlexander Stetsenko 				goto errout;
3644e065a9fSAlexander Stetsenko 			}
3654e065a9fSAlexander Stetsenko 
3664e065a9fSAlexander Stetsenko 			/*
3674e065a9fSAlexander Stetsenko 			 * Get cipher list
3684e065a9fSAlexander Stetsenko 			 */
3694e065a9fSAlexander Stetsenko 			rc = smb_mbc_decodef(
3704e065a9fSAlexander Stetsenko 			    &sr->command, "#w",
3714e065a9fSAlexander Stetsenko 			    encap->encap_cipher_count,
3724e065a9fSAlexander Stetsenko 			    &encap->encap_cipher_ids[0]);	/* w */
3734e065a9fSAlexander Stetsenko 			if (rc != 0) {
3744e065a9fSAlexander Stetsenko 				status = NT_STATUS_INVALID_PARAMETER;
3754e065a9fSAlexander Stetsenko 				goto errout;
3764e065a9fSAlexander Stetsenko 			}
3774e065a9fSAlexander Stetsenko 
378dee7ba86SAlexander Stetsenko 			/*
379dee7ba86SAlexander Stetsenko 			 * Select the first enabled cipher.
380dee7ba86SAlexander Stetsenko 			 * Client should list more prioritized ciphers first.
381dee7ba86SAlexander Stetsenko 			 */
3824e065a9fSAlexander Stetsenko 			for (int k = 0; k < encap->encap_cipher_count; k++) {
383dee7ba86SAlexander Stetsenko 				uint16_t c = encap->encap_cipher_ids[k];
384dee7ba86SAlexander Stetsenko 
385dee7ba86SAlexander Stetsenko 				if (SMB3_CIPHER_ENABLED(c, ciphers)) {
386dee7ba86SAlexander Stetsenko 					s->smb31_enc_cipherid = c;
387dee7ba86SAlexander Stetsenko 					found_cipher = B_TRUE;
3884e065a9fSAlexander Stetsenko 					break;
3894e065a9fSAlexander Stetsenko 				}
3904e065a9fSAlexander Stetsenko 			}
3914e065a9fSAlexander Stetsenko 			break;
3924e065a9fSAlexander Stetsenko 		default:
3934e065a9fSAlexander Stetsenko 			;
3944e065a9fSAlexander Stetsenko 		}
3954e065a9fSAlexander Stetsenko 	}
3964e065a9fSAlexander Stetsenko 
3974e065a9fSAlexander Stetsenko 	if (status)
3984e065a9fSAlexander Stetsenko 		goto errout;
3994e065a9fSAlexander Stetsenko 
4004e065a9fSAlexander Stetsenko 	/* Not found mandatory SMB2_PREAUTH_INTEGRITY_CAPS ctx */
4014e065a9fSAlexander Stetsenko 	if (found_preauth_ctx != 1 || found_encrypt_ctx > 1) {
4024e065a9fSAlexander Stetsenko 		status = NT_STATUS_INVALID_PARAMETER;
4034e065a9fSAlexander Stetsenko 		goto errout;
4044e065a9fSAlexander Stetsenko 	}
4054e065a9fSAlexander Stetsenko 
406dee7ba86SAlexander Stetsenko 	if (!found_sha512) {
4074e065a9fSAlexander Stetsenko 		status = STATUS_PREAUTH_HASH_OVERLAP;
4084e065a9fSAlexander Stetsenko 		goto errout;
4094e065a9fSAlexander Stetsenko 	}
4104e065a9fSAlexander Stetsenko 
4114e065a9fSAlexander Stetsenko 	s->smb31_preauth_hashid = SMB3_HASH_SHA512;
4124e065a9fSAlexander Stetsenko 
413dee7ba86SAlexander Stetsenko 	if (!found_cipher)
4144e065a9fSAlexander Stetsenko 		s->smb31_enc_cipherid = 0;
4154e065a9fSAlexander Stetsenko 
416ab017dbaSGordon Ross 	/* Initialize out = in */
417ab017dbaSGordon Ross 	nego->neg_out_ctxs = nego->neg_in_ctxs;
418ab017dbaSGordon Ross 
4194e065a9fSAlexander Stetsenko errout:
4204e065a9fSAlexander Stetsenko 	return (status);
4214e065a9fSAlexander Stetsenko }
4224e065a9fSAlexander Stetsenko 
4234e065a9fSAlexander Stetsenko static int
424b716e3d0SGordon Ross smb31_encode_neg_ctxs(smb_request_t *sr)
4254e065a9fSAlexander Stetsenko {
4264e065a9fSAlexander Stetsenko 	smb_session_t *s = sr->session;
427b716e3d0SGordon Ross 	smb2_arg_negotiate_t *nego = sr->arg.other;
428b716e3d0SGordon Ross 	smb2_neg_ctxs_t *neg_ctxs = &nego->neg_out_ctxs;
4294e065a9fSAlexander Stetsenko 	smb2_preauth_caps_t *picap = &neg_ctxs->preauth_ctx.preauth_caps;
4304e065a9fSAlexander Stetsenko 	smb2_encrypt_caps_t *encap = &neg_ctxs->encrypt_ctx.encrypt_caps;
4314e065a9fSAlexander Stetsenko 	uint16_t salt_len = sizeof (picap->picap_salt);
4324e065a9fSAlexander Stetsenko 	uint32_t preauth_ctx_len = 6 + salt_len;
4334e065a9fSAlexander Stetsenko 	uint32_t enc_ctx_len = 4;
4344e065a9fSAlexander Stetsenko 	uint32_t neg_ctx_off = NEG_CTX_OFFSET_OFFSET +
4354e065a9fSAlexander Stetsenko 	    P2ROUNDUP(sr->sr_cfg->skc_negtok_len, 8);
4364e065a9fSAlexander Stetsenko 	uint32_t rc;
4374e065a9fSAlexander Stetsenko 
4384e065a9fSAlexander Stetsenko 	if ((rc = smb_mbc_put_align(&sr->reply, 8)) != 0)
4394e065a9fSAlexander Stetsenko 		return (rc);
4404e065a9fSAlexander Stetsenko 
4414e065a9fSAlexander Stetsenko 	ASSERT3S(neg_ctx_off, ==, sr->reply.chain_offset);
4424e065a9fSAlexander Stetsenko 
4434e065a9fSAlexander Stetsenko 	picap->picap_hash_id = s->smb31_preauth_hashid;
4444e065a9fSAlexander Stetsenko 	picap->picap_salt_len = salt_len;
4454e065a9fSAlexander Stetsenko 
4464e065a9fSAlexander Stetsenko 	(void) random_get_pseudo_bytes(picap->picap_salt, salt_len);
4474e065a9fSAlexander Stetsenko 
4484e065a9fSAlexander Stetsenko 	rc = smb_mbc_encodef(
4494e065a9fSAlexander Stetsenko 	    &sr->reply, "ww4.",
4504e065a9fSAlexander Stetsenko 	    SMB2_PREAUTH_INTEGRITY_CAPS,
4514e065a9fSAlexander Stetsenko 	    preauth_ctx_len
4524e065a9fSAlexander Stetsenko 	    /* 4. */); /* reserved */
4534e065a9fSAlexander Stetsenko 	if (rc != 0)
4544e065a9fSAlexander Stetsenko 		return (rc);
4554e065a9fSAlexander Stetsenko 
4564e065a9fSAlexander Stetsenko 	rc = smb_mbc_encodef(
4574e065a9fSAlexander Stetsenko 	    &sr->reply, "www#c",
4584e065a9fSAlexander Stetsenko 	    1,				/* hash algo count */
4594e065a9fSAlexander Stetsenko 	    salt_len,			/* salt length */
4604e065a9fSAlexander Stetsenko 	    s->smb31_preauth_hashid,	/* hash id */
4614e065a9fSAlexander Stetsenko 	    salt_len,			/* salt length */
4624e065a9fSAlexander Stetsenko 	    picap->picap_salt);
463ab017dbaSGordon Ross 	if (rc != 0)
4644e065a9fSAlexander Stetsenko 		return (rc);
4654e065a9fSAlexander Stetsenko 
466ab017dbaSGordon Ross 	/*
467ab017dbaSGordon Ross 	 * If we did not get SMB2_ENCRYPTION_CAPS, don't send one.
468ab017dbaSGordon Ross 	 */
469ab017dbaSGordon Ross 	if (encap->encap_cipher_count == 0)
470ab017dbaSGordon Ross 		return (0);
471ab017dbaSGordon Ross 
472ab017dbaSGordon Ross 	/*
473ab017dbaSGordon Ross 	 * Encode SMB2_ENCRYPTION_CAPS response.
474ab017dbaSGordon Ross 	 */
4754e065a9fSAlexander Stetsenko 	if ((rc = smb_mbc_put_align(&sr->reply, 8)) != 0)
4764e065a9fSAlexander Stetsenko 		return (rc);
4774e065a9fSAlexander Stetsenko 
4784e065a9fSAlexander Stetsenko 	rc = smb_mbc_encodef(
4794e065a9fSAlexander Stetsenko 	    &sr->reply, "ww4.",
4804e065a9fSAlexander Stetsenko 	    SMB2_ENCRYPTION_CAPS,
4814e065a9fSAlexander Stetsenko 	    enc_ctx_len
4824e065a9fSAlexander Stetsenko 	    /* 4. */); /* reserved */
4834e065a9fSAlexander Stetsenko 
4844e065a9fSAlexander Stetsenko 	rc = smb_mbc_encodef(
4854e065a9fSAlexander Stetsenko 	    &sr->reply, "ww",
4864e065a9fSAlexander Stetsenko 	    1,				/* cipher count */
4874e065a9fSAlexander Stetsenko 	    s->smb31_enc_cipherid);	/* encrypt. cipher id */
4884e065a9fSAlexander Stetsenko 
4894e065a9fSAlexander Stetsenko 	return (rc);
4904e065a9fSAlexander Stetsenko }
4914e065a9fSAlexander Stetsenko 
492b716e3d0SGordon Ross /*
493b716e3d0SGordon Ross  * Helper for the (SMB1) smb_com_negotiate().  This is the
494b716e3d0SGordon Ross  * very unusual protocol interaction where an SMB1 negotiate
495b716e3d0SGordon Ross  * gets an SMB2 negotiate response.  This is the normal way
496b716e3d0SGordon Ross  * clients first find out if the server supports SMB2.
497b716e3d0SGordon Ross  *
498b716e3d0SGordon Ross  * Note: This sends an SMB2 reply _itself_ and then returns
499b716e3d0SGordon Ross  * SDRC_NO_REPLY so the caller will not send an SMB1 reply.
500b716e3d0SGordon Ross  * Also, this is called directly from the reader thread, so
501b716e3d0SGordon Ross  * we know this is the only thread using this session.
502b716e3d0SGordon Ross  * Otherwise, this is similar to smb2_newrq_negotiate().
503b716e3d0SGordon Ross  *
504b716e3d0SGordon Ross  * The caller frees this request.
505b716e3d0SGordon Ross  */
506b716e3d0SGordon Ross smb_sdrc_t
507b716e3d0SGordon Ross smb1_negotiate_smb2(smb_request_t *sr)
508b716e3d0SGordon Ross {
509b716e3d0SGordon Ross 	smb_session_t *s = sr->session;
510b716e3d0SGordon Ross 	smb_arg_negotiate_t *negprot = sr->sr_negprot;
511b716e3d0SGordon Ross 	uint16_t smb2_version;
512b716e3d0SGordon Ross 
513b716e3d0SGordon Ross 	/*
514b716e3d0SGordon Ross 	 * Note: In the SMB1 negotiate command handler, we
515b716e3d0SGordon Ross 	 * agreed with one of the SMB2 dialects.  If that
516b716e3d0SGordon Ross 	 * dialect was "SMB 2.002", we'll respond here with
517b716e3d0SGordon Ross 	 * version 0x202 and negotiation is done.  If that
518b716e3d0SGordon Ross 	 * dialect was "SMB 2.???", we'll respond here with
519b716e3d0SGordon Ross 	 * the "wildcard" version 0x2FF, and the client will
520b716e3d0SGordon Ross 	 * come back with an SMB2 negotiate.
521b716e3d0SGordon Ross 	 */
522b716e3d0SGordon Ross 	switch (negprot->ni_dialect) {
523b716e3d0SGordon Ross 	case DIALECT_SMB2002:	/* SMB 2.002 (a.k.a. SMB2.0) */
524b716e3d0SGordon Ross 		smb2_version = SMB_VERS_2_002;
525b716e3d0SGordon Ross 		s->dialect = smb2_version;
526b716e3d0SGordon Ross 		s->s_state = SMB_SESSION_STATE_NEGOTIATED;
527b716e3d0SGordon Ross 		/* Allow normal SMB2 requests now. */
528b716e3d0SGordon Ross 		s->newrq_func = smb2sr_newrq;
529b716e3d0SGordon Ross 		break;
530b716e3d0SGordon Ross 	case DIALECT_SMB2XXX:	/* SMB 2.??? (wildcard vers) */
531b716e3d0SGordon Ross 		/*
532b716e3d0SGordon Ross 		 * Expecting an SMB2 negotiate next, so keep the
533b716e3d0SGordon Ross 		 * initial s->newrq_func.
534b716e3d0SGordon Ross 		 */
535b716e3d0SGordon Ross 		smb2_version = 0x2FF;
536b716e3d0SGordon Ross 		break;
537b716e3d0SGordon Ross 	default:
538b716e3d0SGordon Ross 		return (SDRC_DROP_VC);
539b716e3d0SGordon Ross 	}
540b716e3d0SGordon Ross 
541b716e3d0SGordon Ross 	/*
542b716e3d0SGordon Ross 	 * We did not decode an SMB2 header, so make sure
543b716e3d0SGordon Ross 	 * the SMB2 header fields are initialized.
544b716e3d0SGordon Ross 	 * (Most are zero from smb_request_alloc.)
545b716e3d0SGordon Ross 	 * Also, the SMB1 common dispatch code reserved space
546b716e3d0SGordon Ross 	 * for an SMB1 header, which we need to undo here.
547b716e3d0SGordon Ross 	 */
548b716e3d0SGordon Ross 	sr->smb2_reply_hdr = sr->reply.chain_offset = 0;
549b716e3d0SGordon Ross 	sr->smb2_cmd_code = SMB2_NEGOTIATE;
550b716e3d0SGordon Ross 	sr->smb2_hdr_flags = SMB2_FLAGS_SERVER_TO_REDIR;
551b716e3d0SGordon Ross 
552b716e3d0SGordon Ross 	/*
553b716e3d0SGordon Ross 	 * Also setup SMB2 negotiate args (empty here).
554b716e3d0SGordon Ross 	 * SMB1 args free'd by smb_srm_fini(sr)
555b716e3d0SGordon Ross 	 */
556b716e3d0SGordon Ross 	sr->arg.other = smb_srm_zalloc(sr, sizeof (smb2_arg_negotiate_t));
557b716e3d0SGordon Ross 
558b716e3d0SGordon Ross 	(void) smb2_encode_header(sr, B_FALSE);
559b716e3d0SGordon Ross 	if (smb2_negotiate_common(sr, smb2_version) != 0)
560b716e3d0SGordon Ross 		sr->smb2_status = NT_STATUS_INTERNAL_ERROR;
561b716e3d0SGordon Ross 	if (sr->smb2_status != 0)
562b716e3d0SGordon Ross 		smb2sr_put_error(sr, sr->smb2_status);
563b716e3d0SGordon Ross 	(void) smb2_encode_header(sr, B_TRUE);
564b716e3d0SGordon Ross 
565b716e3d0SGordon Ross 	smb2_send_reply(sr);
566b716e3d0SGordon Ross 
567b716e3d0SGordon Ross 	/*
568b716e3d0SGordon Ross 	 * We sent the reply, so tell the SMB1 dispatch
569b716e3d0SGordon Ross 	 * it should NOT (also) send a reply.
570b716e3d0SGordon Ross 	 */
571b716e3d0SGordon Ross 	return (SDRC_NO_REPLY);
572b716e3d0SGordon Ross }
573b716e3d0SGordon Ross 
574b716e3d0SGordon Ross /*
575b716e3d0SGordon Ross  * SMB2 Negotiate gets special handling.  This is called directly by
576b716e3d0SGordon Ross  * the reader thread (see smbsr_newrq_initial) with what _should_ be
577b716e3d0SGordon Ross  * an SMB2 Negotiate.  Only the "\feSMB" header has been checked
578b716e3d0SGordon Ross  * when this is called, so this needs to check the SMB command,
579b716e3d0SGordon Ross  * if it's Negotiate execute it, then send the reply, etc.
580b716e3d0SGordon Ross  *
581b716e3d0SGordon Ross  * Since this is called directly from the reader thread, we
582b716e3d0SGordon Ross  * know this is the only thread currently using this session.
583b716e3d0SGordon Ross  * This has to duplicate some of what smb2sr_work does as a
584b716e3d0SGordon Ross  * result of bypassing the normal dispatch mechanism.
585b716e3d0SGordon Ross  *
586b716e3d0SGordon Ross  * The caller always frees this request.
587b716e3d0SGordon Ross  *
588b716e3d0SGordon Ross  * Return value is 0 for success, and anything else will
589b716e3d0SGordon Ross  * terminate the reader thread (drop the connection).
590b716e3d0SGordon Ross  */
591a90cf9f2SGordon Ross int
592a90cf9f2SGordon Ross smb2_newrq_negotiate(smb_request_t *sr)
593a90cf9f2SGordon Ross {
594a90cf9f2SGordon Ross 	smb_session_t *s = sr->session;
595b716e3d0SGordon Ross 	smb2_arg_negotiate_t *nego;
5961160dcf7SMatt Barden 	int rc;
597b716e3d0SGordon Ross 	uint32_t nctx_status = 0;
598ebc5aadbSAndrew Stormont 	uint32_t status = 0;
599b716e3d0SGordon Ross 	uint32_t neg_ctx_off;
600b716e3d0SGordon Ross 	uint16_t neg_ctx_cnt;
601a90cf9f2SGordon Ross 	uint16_t struct_size;
602b716e3d0SGordon Ross 	uint16_t dialect_cnt;
603a90cf9f2SGordon Ross 	uint16_t best_version;
6044e065a9fSAlexander Stetsenko 
605b716e3d0SGordon Ross 	nego = smb_srm_zalloc(sr, sizeof (smb2_arg_negotiate_t));
606b716e3d0SGordon Ross 	sr->arg.other = nego;	// for dtrace
607a90cf9f2SGordon Ross 
608a90cf9f2SGordon Ross 	sr->smb2_cmd_hdr = sr->command.chain_offset;
609a90cf9f2SGordon Ross 	rc = smb2_decode_header(sr);
610a90cf9f2SGordon Ross 	if (rc != 0)
611a90cf9f2SGordon Ross 		return (rc);
612a90cf9f2SGordon Ross 
613ebc5aadbSAndrew Stormont 	if (sr->smb2_hdr_flags & SMB2_FLAGS_SERVER_TO_REDIR)
614ebc5aadbSAndrew Stormont 		return (-1);
615ebc5aadbSAndrew Stormont 
616a90cf9f2SGordon Ross 	if ((sr->smb2_cmd_code != SMB2_NEGOTIATE) ||
617a90cf9f2SGordon Ross 	    (sr->smb2_next_command != 0))
61893bc28dbSGordon Ross 		return (-1);
619a90cf9f2SGordon Ross 
620a90cf9f2SGordon Ross 	/*
621a90cf9f2SGordon Ross 	 * Decode SMB2 Negotiate (fixed-size part)
622a90cf9f2SGordon Ross 	 */
623a90cf9f2SGordon Ross 	rc = smb_mbc_decodef(
624b716e3d0SGordon Ross 	    &sr->command, "www..l16clw..",
625a90cf9f2SGordon Ross 	    &struct_size,	/* w */
626b716e3d0SGordon Ross 	    &dialect_cnt,	/* w */
6271160dcf7SMatt Barden 	    &s->cli_secmode,	/* w */
628a90cf9f2SGordon Ross 	    /* reserved		(..) */
6291160dcf7SMatt Barden 	    &s->capabilities,	/* l */
630b716e3d0SGordon Ross 	    s->clnt_uuid,	/* 16c */
631b716e3d0SGordon Ross 	    &neg_ctx_off,	/* l */
632b716e3d0SGordon Ross 	    &neg_ctx_cnt);	/* w */
633b716e3d0SGordon Ross 	    /* reserverd	(..) */
634a90cf9f2SGordon Ross 	if (rc != 0)
635a90cf9f2SGordon Ross 		return (rc);
636ebc5aadbSAndrew Stormont 	if (struct_size != 36)
63793bc28dbSGordon Ross 		return (-1);
638a90cf9f2SGordon Ross 
639a90cf9f2SGordon Ross 	/*
640a90cf9f2SGordon Ross 	 * Decode SMB2 Negotiate (variable part)
641ebc5aadbSAndrew Stormont 	 *
642ebc5aadbSAndrew Stormont 	 * Be somewhat tolerant while decoding the variable part
643ebc5aadbSAndrew Stormont 	 * so we can return errors instead of dropping the client.
6444e065a9fSAlexander Stetsenko 	 * Will limit decoding to the size of cli_dialects here,
645b716e3d0SGordon Ross 	 * and do error checks on the decoded dialect_cnt after the
646ebc5aadbSAndrew Stormont 	 * dtrace start probe.
647a90cf9f2SGordon Ross 	 */
648b716e3d0SGordon Ross 	if (dialect_cnt > SMB2_NEGOTIATE_MAX_DIALECTS)
649b716e3d0SGordon Ross 		nego->neg_dialect_cnt = SMB2_NEGOTIATE_MAX_DIALECTS;
650b716e3d0SGordon Ross 	else
651b716e3d0SGordon Ross 		nego->neg_dialect_cnt = dialect_cnt;
652b716e3d0SGordon Ross 	if (nego->neg_dialect_cnt > 0) {
653b716e3d0SGordon Ross 		rc = smb_mbc_decodef(&sr->command, "#w",
654b716e3d0SGordon Ross 		    nego->neg_dialect_cnt,
655b716e3d0SGordon Ross 		    nego->neg_dialects);
656b716e3d0SGordon Ross 		if (rc != 0)
657b716e3d0SGordon Ross 			return (rc);	// short msg
6584e065a9fSAlexander Stetsenko 	}
6594e065a9fSAlexander Stetsenko 
660b716e3d0SGordon Ross 	best_version = smb2_find_best_dialect(s, nego->neg_dialects,
661b716e3d0SGordon Ross 	    nego->neg_dialect_cnt);
6624e065a9fSAlexander Stetsenko 
6634e065a9fSAlexander Stetsenko 	if (best_version >= SMB_VERS_3_11) {
664b716e3d0SGordon Ross 		nego->neg_in_ctxs.offset = neg_ctx_off;
665b716e3d0SGordon Ross 		nego->neg_in_ctxs.count  = neg_ctx_cnt;
666b716e3d0SGordon Ross 		nctx_status = smb31_decode_neg_ctxs(sr);
667b716e3d0SGordon Ross 		/* check nctx_status below */
668ebc5aadbSAndrew Stormont 	}
66993bc28dbSGordon Ross 
67093bc28dbSGordon Ross 	DTRACE_SMB2_START(op__Negotiate, smb_request_t *, sr);
671a90cf9f2SGordon Ross 
672b716e3d0SGordon Ross 	sr->smb2_credit_response = 1;
673ebc5aadbSAndrew Stormont 	sr->smb2_hdr_flags |= SMB2_FLAGS_SERVER_TO_REDIR;
674ebc5aadbSAndrew Stormont 	(void) smb2_encode_header(sr, B_FALSE);
675ebc5aadbSAndrew Stormont 
676b716e3d0SGordon Ross 	/*
677b716e3d0SGordon Ross 	 * NOW start validating things (NOT before here)
678b716e3d0SGordon Ross 	 */
6794e065a9fSAlexander Stetsenko 
680ebc5aadbSAndrew Stormont 	/*
681ebc5aadbSAndrew Stormont 	 * [MS-SMB2] 3.3.5.2.4 Verifying the Signature
682ebc5aadbSAndrew Stormont 	 * "If the SMB2 header of the SMB2 NEGOTIATE request has the
683ebc5aadbSAndrew Stormont 	 * SMB2_FLAGS_SIGNED bit set in the Flags field, the server
684ebc5aadbSAndrew Stormont 	 * MUST fail the request with STATUS_INVALID_PARAMETER."
685ebc5aadbSAndrew Stormont 	 */
686ebc5aadbSAndrew Stormont 	if ((sr->smb2_hdr_flags & SMB2_FLAGS_SIGNED) != 0) {
687ebc5aadbSAndrew Stormont 		sr->smb2_hdr_flags &= ~SMB2_FLAGS_SIGNED;
688ebc5aadbSAndrew Stormont 		status = NT_STATUS_INVALID_PARAMETER;
689ebc5aadbSAndrew Stormont 		goto errout;
690ebc5aadbSAndrew Stormont 	}
691ebc5aadbSAndrew Stormont 
692b716e3d0SGordon Ross 	/*
693b716e3d0SGordon Ross 	 * [MS-SMB2] 3.3.5.4 Receiving an SMB2 NEGOTIATE Request
694b716e3d0SGordon Ross 	 * "If the DialectCount of the SMB2 NEGOTIATE Request is 0, the
695b716e3d0SGordon Ross 	 * server MUST fail the request with STATUS_INVALID_PARAMETER."
696b716e3d0SGordon Ross 	 * Checking the decoded value here, not the constrained one.
697b716e3d0SGordon Ross 	 */
698b716e3d0SGordon Ross 	if (dialect_cnt == 0 ||
699b716e3d0SGordon Ross 	    dialect_cnt > SMB2_NEGOTIATE_MAX_DIALECTS) {
700b716e3d0SGordon Ross 		status = NT_STATUS_INVALID_PARAMETER;
701b716e3d0SGordon Ross 		goto errout;
702b716e3d0SGordon Ross 	}
703b716e3d0SGordon Ross 
704b716e3d0SGordon Ross 	/*
705b716e3d0SGordon Ross 	 * We decoded the offered dialects above, and
706b716e3d0SGordon Ross 	 * determined which was the highest we support.
707b716e3d0SGordon Ross 	 *
708b716e3d0SGordon Ross 	 * [MS-SMB2] 3.3.5.4 Receiving an SMB2 NEGOTIATE Request
709b716e3d0SGordon Ross 	 * "If a common dialect is not found, the server MUST fail
710b716e3d0SGordon Ross 	 * the request with STATUS_NOT_SUPPORTED."
711b716e3d0SGordon Ross 	 */
712b716e3d0SGordon Ross 	if (best_version == 0) {
713b716e3d0SGordon Ross 		status = NT_STATUS_NOT_SUPPORTED;
714b716e3d0SGordon Ross 		goto errout;
715b716e3d0SGordon Ross 	}
716b716e3d0SGordon Ross 
717b716e3d0SGordon Ross 	/*
718b716e3d0SGordon Ross 	 * Check for problems with the negotiate contexts.
719b716e3d0SGordon Ross 	 */
720b716e3d0SGordon Ross 	if (nctx_status != 0) {
721b716e3d0SGordon Ross 		status = nctx_status;
722b716e3d0SGordon Ross 		goto errout;
723b716e3d0SGordon Ross 	}
724a90cf9f2SGordon Ross 
725a90cf9f2SGordon Ross 	/* Allow normal SMB2 requests now. */
726b716e3d0SGordon Ross 	s->dialect = best_version;
727a90cf9f2SGordon Ross 	s->s_state = SMB_SESSION_STATE_NEGOTIATED;
728a90cf9f2SGordon Ross 	s->newrq_func = smb2sr_newrq;
729a90cf9f2SGordon Ross 
730ebc5aadbSAndrew Stormont 	if (smb2_negotiate_common(sr, best_version) != 0)
731ebc5aadbSAndrew Stormont 		status = NT_STATUS_INTERNAL_ERROR;
732a90cf9f2SGordon Ross 
7334e065a9fSAlexander Stetsenko 	if (s->dialect >= SMB_VERS_3_11 && status == 0) {
734b716e3d0SGordon Ross 		if (smb31_encode_neg_ctxs(sr) != 0)
7354e065a9fSAlexander Stetsenko 			status = NT_STATUS_INTERNAL_ERROR;
7364e065a9fSAlexander Stetsenko 	}
7374e065a9fSAlexander Stetsenko 
7383e2c0c09SMatt Barden errout:
739ebc5aadbSAndrew Stormont 	sr->smb2_status = status;
74093bc28dbSGordon Ross 	DTRACE_SMB2_DONE(op__Negotiate, smb_request_t *, sr);
74193bc28dbSGordon Ross 
742ebc5aadbSAndrew Stormont 	if (sr->smb2_status != 0)
743ebc5aadbSAndrew Stormont 		smb2sr_put_error(sr, sr->smb2_status);
744ebc5aadbSAndrew Stormont 	(void) smb2_encode_header(sr, B_TRUE);
745ebc5aadbSAndrew Stormont 
7464e065a9fSAlexander Stetsenko 	if (s->dialect >= SMB_VERS_3_11 && sr->smb2_status == 0) {
7474e065a9fSAlexander Stetsenko 		ASSERT3U(s->smb31_preauth_hashid, !=, 0);
7484e065a9fSAlexander Stetsenko 		if (smb31_preauth_sha512_calc(sr, &sr->reply,
7494e065a9fSAlexander Stetsenko 		    s->smb31_preauth_hashval,
7504e065a9fSAlexander Stetsenko 		    s->smb31_preauth_hashval) != 0)
7514e065a9fSAlexander Stetsenko 			cmn_err(CE_WARN, "(1) Preauth hash calculation "
7524e065a9fSAlexander Stetsenko 			    "failed");
7534e065a9fSAlexander Stetsenko 	}
7544e065a9fSAlexander Stetsenko 
75593bc28dbSGordon Ross 	smb2_send_reply(sr);
75693bc28dbSGordon Ross 
75793bc28dbSGordon Ross 	return (rc);
758a90cf9f2SGordon Ross }
759a90cf9f2SGordon Ross 
760a90cf9f2SGordon Ross /*
761a90cf9f2SGordon Ross  * Common parts of SMB2 Negotiate, used for both the
762a90cf9f2SGordon Ross  * SMB1-to-SMB2 style, and straight SMB2 style.
76393bc28dbSGordon Ross  * Do negotiation decisions and encode the reply.
76493bc28dbSGordon Ross  * The caller does the network send.
76593bc28dbSGordon Ross  *
766ebc5aadbSAndrew Stormont  * Return value is 0 for success, else error.
767a90cf9f2SGordon Ross  */
768a90cf9f2SGordon Ross static int
769a90cf9f2SGordon Ross smb2_negotiate_common(smb_request_t *sr, uint16_t version)
770a90cf9f2SGordon Ross {
771a90cf9f2SGordon Ross 	timestruc_t boot_tv, now_tv;
772a90cf9f2SGordon Ross 	smb_session_t *s = sr->session;
773ab017dbaSGordon Ross 	smb2_arg_negotiate_t *nego = sr->arg.other;
774a90cf9f2SGordon Ross 	int rc;
775aa321b3cSDan McDonald 	uint32_t max_rwsize;
776a90cf9f2SGordon Ross 	uint16_t secmode;
7774e065a9fSAlexander Stetsenko 	uint16_t neg_ctx_cnt = 0;
7784e065a9fSAlexander Stetsenko 	uint32_t neg_ctx_off = 0;
779a90cf9f2SGordon Ross 
780a90cf9f2SGordon Ross 	/*
781a90cf9f2SGordon Ross 	 * Negotiation itself.  First the Security Mode.
782a90cf9f2SGordon Ross 	 */
783a90cf9f2SGordon Ross 	secmode = SMB2_NEGOTIATE_SIGNING_ENABLED;
784ebc5aadbSAndrew Stormont 	if (sr->sr_cfg->skc_signing_required)
785a90cf9f2SGordon Ross 		secmode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
7861160dcf7SMatt Barden 	s->srv_secmode = secmode;
787a90cf9f2SGordon Ross 
788a90cf9f2SGordon Ross 	s->cmd_max_bytes = smb2_tcp_bufsize;
789a90cf9f2SGordon Ross 	s->reply_max_bytes = smb2_tcp_bufsize;
790a90cf9f2SGordon Ross 
791a90cf9f2SGordon Ross 	/*
792a90cf9f2SGordon Ross 	 * "The number of credits held by the client MUST be considered
793a90cf9f2SGordon Ross 	 * as 1 when the connection is established." [MS-SMB2]
794a90cf9f2SGordon Ross 	 * We leave credits at 1 until the first successful
795a90cf9f2SGordon Ross 	 * session setup is completed.
796a90cf9f2SGordon Ross 	 */
797a90cf9f2SGordon Ross 	s->s_cur_credits = s->s_max_credits = 1;
798a90cf9f2SGordon Ross 	sr->smb2_credit_response = 1;
799a90cf9f2SGordon Ross 
800a90cf9f2SGordon Ross 	boot_tv.tv_sec = smb_get_boottime();
801a90cf9f2SGordon Ross 	boot_tv.tv_nsec = 0;
802a90cf9f2SGordon Ross 	now_tv.tv_sec = gethrestime_sec();
803a90cf9f2SGordon Ross 	now_tv.tv_nsec = 0;
804a90cf9f2SGordon Ross 
805a90cf9f2SGordon Ross 	/*
806c51c88bdSMatt Barden 	 * If the version is 0x2FF, we haven't completed negotiate.
807c51c88bdSMatt Barden 	 * Don't initialize until we have our final request.
808c51c88bdSMatt Barden 	 */
809c51c88bdSMatt Barden 	if (version != 0x2FF)
810c51c88bdSMatt Barden 		smb2_sign_init_mech(s);
8114e065a9fSAlexander Stetsenko 	if (version >= 0x311)
8124e065a9fSAlexander Stetsenko 		smb31_preauth_init_mech(s);
813c51c88bdSMatt Barden 
814c51c88bdSMatt Barden 	/*
8151160dcf7SMatt Barden 	 * [MS-SMB2] 3.3.5.4 Receiving an SMB2 NEGOTIATE Request
8161160dcf7SMatt Barden 	 *
8178d94f651SGordon Ross 	 * The SMB2.x capabilities are returned without regard for
8188d94f651SGordon Ross 	 * what capabilities the client provided in the request.
8198d94f651SGordon Ross 	 * The SMB3.x capabilities returned are the traditional
820ab017dbaSGordon Ross 	 * logical AND of server and client capabilities, except
821ab017dbaSGordon Ross 	 * for the SMB2.x capabilities which are what the server
822ab017dbaSGordon Ross 	 * supports (regardless of the client capabilities).
8238d94f651SGordon Ross 	 *
8248d94f651SGordon Ross 	 * One additional check: If KCF is missing something we
8258d94f651SGordon Ross 	 * require for encryption, turn off that capability.
8261160dcf7SMatt Barden 	 */
827700daa96SAndrew Stormont 	if (s->dialect < SMB_VERS_2_1) {
828700daa96SAndrew Stormont 		/* SMB 2.002 */
829700daa96SAndrew Stormont 		s->srv_cap = smb2srv_capabilities & SMB2_CAP_DFS;
830700daa96SAndrew Stormont 	} else if (s->dialect < SMB_VERS_3_0) {
8318d94f651SGordon Ross 		/* SMB 2.x */
8328d94f651SGordon Ross 		s->srv_cap = smb2srv_capabilities & SMB_2X_CAPS;
8338d94f651SGordon Ross 	} else {
8348d94f651SGordon Ross 		/* SMB 3.0 or later */
8358d94f651SGordon Ross 		s->srv_cap = smb2srv_capabilities &
8368d94f651SGordon Ross 		    (SMB_2X_CAPS | s->capabilities);
837ab017dbaSGordon Ross 
838ab017dbaSGordon Ross 		if (s->dialect < SMB_VERS_3_11)
839ab017dbaSGordon Ross 			s->smb31_enc_cipherid = SMB3_CIPHER_AES128_CCM;
840ab017dbaSGordon Ross 		/* else from negotiate context */
841ab017dbaSGordon Ross 
8428d94f651SGordon Ross 		if ((s->srv_cap & SMB2_CAP_ENCRYPTION) != 0 &&
8438d94f651SGordon Ross 		    smb3_encrypt_init_mech(s) != 0) {
8448d94f651SGordon Ross 			s->srv_cap &= ~SMB2_CAP_ENCRYPTION;
8454e065a9fSAlexander Stetsenko 		}
8464e065a9fSAlexander Stetsenko 
8474e065a9fSAlexander Stetsenko 		if (s->dialect >= SMB_VERS_3_11) {
848ab017dbaSGordon Ross 			smb2_encrypt_caps_t *encap =
849ab017dbaSGordon Ross 			    &nego->neg_in_ctxs.encrypt_ctx.encrypt_caps;
850ab017dbaSGordon Ross 
851ab017dbaSGordon Ross 			neg_ctx_cnt = 1; // always have preauth
852ab017dbaSGordon Ross 
853ab017dbaSGordon Ross 			if (encap->encap_cipher_count != 0)
854ab017dbaSGordon Ross 				neg_ctx_cnt++;
855ab017dbaSGordon Ross 
8564e065a9fSAlexander Stetsenko 			neg_ctx_off = NEG_CTX_OFFSET_OFFSET +
8574e065a9fSAlexander Stetsenko 			    P2ROUNDUP(sr->sr_cfg->skc_negtok_len, 8);
8584e065a9fSAlexander Stetsenko 
8594e065a9fSAlexander Stetsenko 			ASSERT3U(s->smb31_preauth_hashid, !=, 0);
8604e065a9fSAlexander Stetsenko 
8614e065a9fSAlexander Stetsenko 			if (smb31_preauth_sha512_calc(sr, &sr->command,
8624e065a9fSAlexander Stetsenko 			    s->smb31_preauth_hashval,
8634e065a9fSAlexander Stetsenko 			    s->smb31_preauth_hashval) != 0)
8644e065a9fSAlexander Stetsenko 				cmn_err(CE_WARN, "(0) Preauth hash calculation "
8654e065a9fSAlexander Stetsenko 				    "failed");
8668d94f651SGordon Ross 		}
8678d94f651SGordon Ross 	}
8681160dcf7SMatt Barden 
8691160dcf7SMatt Barden 	/*
870aa321b3cSDan McDonald 	 * See notes above smb2_max_rwsize, smb2_old_rwsize
871aa321b3cSDan McDonald 	 */
872aa321b3cSDan McDonald 	if (s->capabilities & SMB2_CAP_LARGE_MTU)
873aa321b3cSDan McDonald 		max_rwsize = smb2_max_rwsize;
874aa321b3cSDan McDonald 	else
875aa321b3cSDan McDonald 		max_rwsize = smb2_old_rwsize;
876aa321b3cSDan McDonald 
877a90cf9f2SGordon Ross 	rc = smb_mbc_encodef(
878a90cf9f2SGordon Ross 	    &sr->reply,
879a90cf9f2SGordon Ross 	    "wwww#cllllTTwwl#c",
880a90cf9f2SGordon Ross 	    65,	/* StructSize */	/* w */
8811160dcf7SMatt Barden 	    s->srv_secmode,		/* w */
882a90cf9f2SGordon Ross 	    version,			/* w */
8834e065a9fSAlexander Stetsenko 	    neg_ctx_cnt,		/* w */
884a90cf9f2SGordon Ross 	    UUID_LEN,			/* # */
885a90cf9f2SGordon Ross 	    &s->s_cfg.skc_machine_uuid, /* c */
8861160dcf7SMatt Barden 	    s->srv_cap,			/* l */
887a90cf9f2SGordon Ross 	    smb2_max_trans,		/* l */
888aa321b3cSDan McDonald 	    max_rwsize,			/* l */
889aa321b3cSDan McDonald 	    max_rwsize,			/* l */
890a90cf9f2SGordon Ross 	    &now_tv,			/* T */
891a90cf9f2SGordon Ross 	    &boot_tv,			/* T */
892a90cf9f2SGordon Ross 	    128, /* SecBufOff */	/* w */
893a90cf9f2SGordon Ross 	    sr->sr_cfg->skc_negtok_len,	/* w */
8944e065a9fSAlexander Stetsenko 	    neg_ctx_off,		/* l */
895a90cf9f2SGordon Ross 	    sr->sr_cfg->skc_negtok_len,	/* # */
896a90cf9f2SGordon Ross 	    sr->sr_cfg->skc_negtok);	/* c */
897a90cf9f2SGordon Ross 
898ab017dbaSGordon Ross 	/* Note: smb31_encode_neg_ctxs() follows in caller */
8994e065a9fSAlexander Stetsenko 
90093bc28dbSGordon Ross 	/* smb2_send_reply(sr); in caller */
901a90cf9f2SGordon Ross 
902a90cf9f2SGordon Ross 	(void) ksocket_setsockopt(s->sock, SOL_SOCKET,
903a90cf9f2SGordon Ross 	    SO_SNDBUF, (const void *)&smb2_tcp_bufsize,
904a90cf9f2SGordon Ross 	    sizeof (smb2_tcp_bufsize), CRED());
905a90cf9f2SGordon Ross 	(void) ksocket_setsockopt(s->sock, SOL_SOCKET,
906a90cf9f2SGordon Ross 	    SO_RCVBUF, (const void *)&smb2_tcp_bufsize,
907a90cf9f2SGordon Ross 	    sizeof (smb2_tcp_bufsize), CRED());
908a90cf9f2SGordon Ross 
909a90cf9f2SGordon Ross 	return (rc);
910a90cf9f2SGordon Ross }
911a90cf9f2SGordon Ross 
912a90cf9f2SGordon Ross /*
913a90cf9f2SGordon Ross  * SMB2 Dispatch table handler, which will run if we see an
914a90cf9f2SGordon Ross  * SMB2_NEGOTIATE after the initial negotiation is done.
915a90cf9f2SGordon Ross  * That would be a protocol error.
916a90cf9f2SGordon Ross  */
917a90cf9f2SGordon Ross smb_sdrc_t
918a90cf9f2SGordon Ross smb2_negotiate(smb_request_t *sr)
919a90cf9f2SGordon Ross {
920a90cf9f2SGordon Ross 	sr->smb2_status = NT_STATUS_INVALID_PARAMETER;
921a90cf9f2SGordon Ross 	return (SDRC_ERROR);
922a90cf9f2SGordon Ross }
923a90cf9f2SGordon Ross 
924a90cf9f2SGordon Ross /*
925a90cf9f2SGordon Ross  * VALIDATE_NEGOTIATE_INFO [MS-SMB2] 2.2.32.6
926a90cf9f2SGordon Ross  */
927a90cf9f2SGordon Ross uint32_t
92855f0a249SGordon Ross smb2_nego_validate(smb_request_t *sr, smb_fsctl_t *fsctl)
929a90cf9f2SGordon Ross {
930a90cf9f2SGordon Ross 	smb_session_t *s = sr->session;
931a90cf9f2SGordon Ross 	int rc;
932a90cf9f2SGordon Ross 
933a90cf9f2SGordon Ross 	/*
934a90cf9f2SGordon Ross 	 * The spec. says to parse the VALIDATE_NEGOTIATE_INFO here
935a90cf9f2SGordon Ross 	 * and verify that the original negotiate was not modified.
936a90cf9f2SGordon Ross 	 *
937a90cf9f2SGordon Ross 	 * One interesting requirement here is that we MUST reply
938a90cf9f2SGordon Ross 	 * with exactly the same information as we returned in our
939a90cf9f2SGordon Ross 	 * original reply to the SMB2 negotiate on this session.
940a90cf9f2SGordon Ross 	 * If we don't the client closes the connection.
941a90cf9f2SGordon Ross 	 */
942a90cf9f2SGordon Ross 
9431160dcf7SMatt Barden 	uint32_t capabilities;
9444e065a9fSAlexander Stetsenko 	uint16_t secmode;
9454e065a9fSAlexander Stetsenko 	uint16_t num_dialects;
9464e065a9fSAlexander Stetsenko 	uint16_t dialects[SMB2_NEGOTIATE_MAX_DIALECTS];
9471160dcf7SMatt Barden 	uint8_t clnt_guid[16];
9481160dcf7SMatt Barden 
9494e065a9fSAlexander Stetsenko 	if (s->dialect >= SMB_VERS_3_11)
9504e065a9fSAlexander Stetsenko 		goto drop;
9514e065a9fSAlexander Stetsenko 
952715c0bc6SAndrew Stormont 	/*
953715c0bc6SAndrew Stormont 	 * [MS-SMB2] 3.3.5.2.4 Verifying the Signature
954715c0bc6SAndrew Stormont 	 *
955715c0bc6SAndrew Stormont 	 * If the dialect is SMB3 and the message was successfully
956715c0bc6SAndrew Stormont 	 * decrypted we MUST skip processing of the signature.
957715c0bc6SAndrew Stormont 	 */
958715c0bc6SAndrew Stormont 	if (!sr->encrypted && (sr->smb2_hdr_flags & SMB2_FLAGS_SIGNED) == 0)
9594ad35fa3SMatt Barden 		goto drop;
9604ad35fa3SMatt Barden 
9611160dcf7SMatt Barden 	if (fsctl->InputCount < 24)
9621160dcf7SMatt Barden 		goto drop;
9631160dcf7SMatt Barden 
9641160dcf7SMatt Barden 	(void) smb_mbc_decodef(fsctl->in_mbc, "l16cww",
9651160dcf7SMatt Barden 	    &capabilities, /* l */
9661160dcf7SMatt Barden 	    &clnt_guid, /* 16c */
9671160dcf7SMatt Barden 	    &secmode, /* w */
9681160dcf7SMatt Barden 	    &num_dialects); /* w */
9691160dcf7SMatt Barden 
9704e065a9fSAlexander Stetsenko 	if (num_dialects == 0 || num_dialects > SMB2_NEGOTIATE_MAX_DIALECTS)
9714e065a9fSAlexander Stetsenko 		goto drop;
9721160dcf7SMatt Barden 	if (secmode != s->cli_secmode)
9731160dcf7SMatt Barden 		goto drop;
9741160dcf7SMatt Barden 	if (capabilities != s->capabilities)
9751160dcf7SMatt Barden 		goto drop;
9761160dcf7SMatt Barden 	if (memcmp(clnt_guid, s->clnt_uuid, sizeof (clnt_guid)) != 0)
9771160dcf7SMatt Barden 		goto drop;
9781160dcf7SMatt Barden 
9791160dcf7SMatt Barden 	rc = smb_mbc_decodef(fsctl->in_mbc, "#w", num_dialects, dialects);
9801160dcf7SMatt Barden 	if (rc != 0)
9811160dcf7SMatt Barden 		goto drop;
9821160dcf7SMatt Barden 
983b716e3d0SGordon Ross 	/*
984b716e3d0SGordon Ross 	 * MS-SMB2 says we should compare the dialects array with the
985b716e3d0SGordon Ross 	 * one sent previously, but that appears to be unnecessary
986b716e3d0SGordon Ross 	 * as long as we end up with the same dialect.
987b716e3d0SGordon Ross 	 */
988b716e3d0SGordon Ross 	if (smb2_find_best_dialect(s, dialects, num_dialects) != s->dialect)
9891160dcf7SMatt Barden 		goto drop;
9901160dcf7SMatt Barden 
991a90cf9f2SGordon Ross 	rc = smb_mbc_encodef(
992a90cf9f2SGordon Ross 	    fsctl->out_mbc, "l#cww",
9931160dcf7SMatt Barden 	    s->srv_cap,			/* l */
994a90cf9f2SGordon Ross 	    UUID_LEN,			/* # */
995a90cf9f2SGordon Ross 	    &s->s_cfg.skc_machine_uuid, /* c */
9961160dcf7SMatt Barden 	    s->srv_secmode,		/* w */
997a90cf9f2SGordon Ross 	    s->dialect);		/* w */
9981160dcf7SMatt Barden 	if (rc == 0)
9991160dcf7SMatt Barden 		return (rc);
1000a90cf9f2SGordon Ross 
10011160dcf7SMatt Barden drop:
10021160dcf7SMatt Barden 	smb_session_disconnect(s);
10031160dcf7SMatt Barden 	return (NT_STATUS_ACCESS_DENIED);
1004a90cf9f2SGordon Ross }
1005