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 PrevSessionId; 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 &PrevSessionId); /* 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 * The real auth. work happens in here. 91 */ 92 status = smb_authenticate_ext(sr); 93 94 SecBufOffset = SMB2_HDR_SIZE + 8; 95 SecBufLength = sinfo->ssi_oseclen; 96 SessionFlags = 0; 97 98 switch (status) { 99 100 case NT_STATUS_SUCCESS: /* Authenticated */ 101 if (sr->uid_user->u_flags & SMB_USER_FLAG_GUEST) 102 SessionFlags |= SMB2_SESSION_FLAG_IS_GUEST; 103 if (sr->uid_user->u_flags & SMB_USER_FLAG_ANON) 104 SessionFlags |= SMB2_SESSION_FLAG_IS_NULL; 105 smb2_ss_adjust_credits(sr); 106 break; 107 108 /* 109 * This is not really an error, but tells the client 110 * it should send another session setup request. 111 * Not smb2_put_error because we send a payload. 112 */ 113 case NT_STATUS_MORE_PROCESSING_REQUIRED: 114 sr->smb2_status = status; 115 break; 116 117 default: 118 SecBufLength = 0; 119 sr->smb2_status = status; 120 break; 121 } 122 123 /* sr->smb2_status set above */ 124 DTRACE_SMB2_DONE(op__SessionSetup, smb_request_t *, sr); 125 126 /* 127 * SMB2 Session Setup reply 128 */ 129 130 rc = smb_mbc_encodef( 131 &sr->reply, 132 "wwww#c", 133 9, /* StructSize */ /* w */ 134 SessionFlags, /* w */ 135 SecBufOffset, /* w */ 136 SecBufLength, /* w */ 137 SecBufLength, /* # */ 138 sinfo->ssi_osecblob); /* c */ 139 if (rc) 140 sr->smb2_status = NT_STATUS_INTERNAL_ERROR; 141 142 return (SDRC_SUCCESS); 143 } 144 145 /* 146 * After a successful authentication, raise s_max_credits up to the 147 * normal maximum that clients are allowed to request. Also, if we 148 * haven't yet given them their initial credits, do that now. 149 * 150 * Normally, clients will request some credits with session setup, 151 * but in case they don't request enough to raise s_cur_credits 152 * up to the configured initial_credits, increase the requested 153 * credits of this SR sufficiently to make that happen. The actual 154 * increase happens in the dispatch code after we return. 155 */ 156 static void 157 smb2_ss_adjust_credits(smb_request_t *sr) 158 { 159 smb_session_t *s = sr->session; 160 161 mutex_enter(&s->s_credits_mutex); 162 s->s_max_credits = s->s_cfg.skc_maximum_credits; 163 164 if (s->s_cur_credits < s->s_cfg.skc_initial_credits) { 165 uint16_t grant; 166 167 /* How many credits we want to grant with this SR. */ 168 grant = s->s_cfg.skc_initial_credits - s->s_cur_credits; 169 170 /* 171 * Do we need to increase the smb2_credit_request? 172 * One might prefer to read this expression as: 173 * ((credit_request - credit_charge) < grant) 174 * but we know credit_charge == 1 and would rather not 175 * deal with a possibly negative value on the left, 176 * so adding credit_charge to both sides... 177 */ 178 if (sr->smb2_credit_request < (grant + 1)) { 179 sr->smb2_credit_request = (grant + 1); 180 } 181 } 182 183 mutex_exit(&s->s_credits_mutex); 184 } 185