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