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