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