1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2017 Nexenta Systems, Inc. All rights reserved. 14 * Copyright 2020 RackTop Systems, Inc. 15 */ 16 17 /* 18 * Dispatch function for SMB2_SESSION_SETUP 19 * 20 * Note that the Capabilities supplied in this request are an inferior 21 * subset of those given to us previously in the SMB2 Negotiate request. 22 * We need to remember the full set of capabilities from SMB2 Negotiate, 23 * and therefore ignore the subset of capabilities supplied here. 24 */ 25 26 #include <smbsrv/smb2_kproto.h> 27 28 static void smb2_ss_adjust_credits(smb_request_t *); 29 30 smb_sdrc_t 31 smb2_session_setup(smb_request_t *sr) 32 { 33 smb_arg_sessionsetup_t *sinfo; 34 smb_session_t *s = sr->session; 35 uint16_t StructureSize; 36 uint8_t Flags; 37 uint8_t SecurityMode; 38 uint32_t Capabilities; /* ignored - see above */ 39 uint32_t Channel; 40 uint16_t SecBufOffset; 41 uint16_t SecBufLength; 42 uint64_t PrevSsnId; 43 uint16_t SessionFlags; 44 uint32_t status; 45 int skip; 46 int rc = 0; 47 48 sinfo = smb_srm_zalloc(sr, sizeof (smb_arg_sessionsetup_t)); 49 sr->sr_ssetup = sinfo; 50 51 rc = smb_mbc_decodef( 52 &sr->smb_data, "wbbllwwq", 53 &StructureSize, /* w */ 54 &Flags, /* b */ 55 &SecurityMode, /* b */ 56 &Capabilities, /* l */ 57 &Channel, /* l */ 58 &SecBufOffset, /* w */ 59 &SecBufLength, /* w */ 60 &PrevSsnId); /* q */ 61 if (rc) 62 return (SDRC_ERROR); 63 64 /* 65 * We're normally positioned at the security buffer now, 66 * but there could be some padding before it. 67 */ 68 skip = (SecBufOffset + sr->smb2_cmd_hdr) - 69 sr->smb_data.chain_offset; 70 if (skip < 0) 71 return (SDRC_ERROR); 72 if (skip > 0) 73 (void) smb_mbc_decodef(&sr->smb_data, "#.", skip); 74 75 /* 76 * Get the security buffer 77 */ 78 sinfo->ssi_iseclen = SecBufLength; 79 sinfo->ssi_isecblob = smb_srm_zalloc(sr, sinfo->ssi_iseclen); 80 rc = smb_mbc_decodef(&sr->smb_data, "#c", 81 sinfo->ssi_iseclen, sinfo->ssi_isecblob); 82 if (rc) 83 return (SDRC_ERROR); 84 85 if (s->dialect >= SMB_VERS_3_11) { 86 ASSERT3U(s->smb31_preauth_hashid, !=, 0); 87 (void) smb31_preauth_sha512_calc(sr, &sr->command, 88 s->smb31_preauth_hashval); 89 } 90 91 /* 92 * Decoded everything. Dtrace probe, 93 * then no more early returns. 94 */ 95 DTRACE_SMB2_START(op__SessionSetup, smb_request_t *, sr); 96 97 /* 98 * [MS-SMB2] 3.3.5.5 Receiving an SMB2 SESSION_SETUP Request 99 * 100 * If we support 3.x, RejectUnencryptedAccess is TRUE, 101 * global EncryptData is TRUE, but we're not talking 102 * 3.x or the client doesn't support encryption, 103 * return ACCESS_DENIED. 104 * 105 * If RejectUnencryptedAccess is TRUE, we force max_protocol 106 * to at least 3.0. 107 */ 108 if (sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED && 109 (sr->session->dialect < SMB_VERS_3_0 || 110 !SMB3_CLIENT_ENCRYPTS(sr))) { 111 status = NT_STATUS_ACCESS_DENIED; 112 goto errout; 113 } 114 115 /* 116 * SMB3 multi-channel features are not supported. 117 * Once they are, this will check the dialect and 118 * whether multi-channel was negotiated, i.e. 119 * if (sr->session->dialect < SMB_VERS_3_0 || 120 * s->IsMultiChannelCapable == False) 121 * return (error...) 122 */ 123 if (Flags & SMB2_SESSION_FLAG_BINDING) { 124 status = NT_STATUS_REQUEST_NOT_ACCEPTED; 125 goto errout; 126 } 127 128 /* 129 * The real auth. work happens in here. 130 */ 131 status = smb_authenticate_ext(sr); 132 133 SecBufOffset = SMB2_HDR_SIZE + 8; 134 SecBufLength = sinfo->ssi_oseclen; 135 SessionFlags = 0; 136 137 switch (status) { 138 139 case NT_STATUS_SUCCESS: /* Authenticated */ 140 if ((sr->uid_user->u_flags & SMB_USER_FLAG_GUEST) != 0) 141 SessionFlags |= SMB2_SESSION_FLAG_IS_GUEST; 142 if ((sr->uid_user->u_flags & SMB_USER_FLAG_ANON) != 0) 143 SessionFlags |= SMB2_SESSION_FLAG_IS_NULL; 144 if (sr->uid_user->u_encrypt != SMB_CONFIG_DISABLED) 145 SessionFlags |= SMB2_SESSION_FLAG_ENCRYPT_DATA; 146 smb2_ss_adjust_credits(sr); 147 148 /* 149 * PrevSsnId is a session that the client is reporting as 150 * having gone away, and for which we might not yet have seen 151 * a disconnect. We need to log off the previous session so 152 * any durable handles in that session will become orphans 153 * that can be reclaimed in this new session. Note that 154 * either zero or the _current_ session ID means there is 155 * no previous session to logoff. 156 */ 157 if (PrevSsnId != 0 && 158 PrevSsnId != sr->smb2_ssnid) 159 smb_server_logoff_ssnid(sr, PrevSsnId); 160 break; 161 162 /* 163 * This is not really an error, but tells the client 164 * it should send another session setup request. 165 * Not smb2_put_error because we send a payload. 166 */ 167 case NT_STATUS_MORE_PROCESSING_REQUIRED: 168 sr->smb2_status = status; 169 break; 170 171 default: 172 errout: 173 SecBufLength = 0; 174 sr->smb2_status = status; 175 break; 176 } 177 178 /* sr->smb2_status set above */ 179 DTRACE_SMB2_DONE(op__SessionSetup, smb_request_t *, sr); 180 181 /* 182 * SMB2 Session Setup reply 183 */ 184 185 rc = smb_mbc_encodef( 186 &sr->reply, 187 "wwww#c", 188 9, /* StructSize */ /* w */ 189 SessionFlags, /* w */ 190 SecBufOffset, /* w */ 191 SecBufLength, /* w */ 192 SecBufLength, /* # */ 193 sinfo->ssi_osecblob); /* c */ 194 if (rc) 195 sr->smb2_status = NT_STATUS_INTERNAL_ERROR; 196 197 return (SDRC_SUCCESS); 198 } 199 200 /* 201 * After a successful authentication, raise s_max_credits up to the 202 * normal maximum that clients are allowed to request. Also, if we 203 * haven't yet given them their initial credits, do that now. 204 * 205 * Normally, clients will request some credits with session setup, 206 * but in case they don't request enough to raise s_cur_credits 207 * up to the configured initial_credits, increase the requested 208 * credits of this SR sufficiently to make that happen. The actual 209 * increase happens in the dispatch code after we return. 210 */ 211 static void 212 smb2_ss_adjust_credits(smb_request_t *sr) 213 { 214 smb_session_t *s = sr->session; 215 216 mutex_enter(&s->s_credits_mutex); 217 s->s_max_credits = s->s_cfg.skc_maximum_credits; 218 219 if (s->s_cur_credits < s->s_cfg.skc_initial_credits) { 220 uint16_t grant; 221 222 /* How many credits we want to grant with this SR. */ 223 grant = s->s_cfg.skc_initial_credits - s->s_cur_credits; 224 225 /* 226 * Do we need to increase the smb2_credit_request? 227 * One might prefer to read this expression as: 228 * ((credit_request - credit_charge) < grant) 229 * but we know credit_charge == 1 and would rather not 230 * deal with a possibly negative value on the left, 231 * so adding credit_charge to both sides... 232 */ 233 if (sr->smb2_credit_request < (grant + 1)) { 234 sr->smb2_credit_request = (grant + 1); 235 } 236 } 237 238 mutex_exit(&s->s_credits_mutex); 239 }