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 }