1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 #include <sys/types.h>
  27 #include <sys/sid.h>
  28 #include <sys/priv_names.h>
  29 #include <sys/socket.h>
  30 #include <netinet/in.h>
  31 #include <smbsrv/smb_idmap.h>
  32 #include <smbsrv/smb_kproto.h>
  33 #include <smbsrv/smb_token.h>
  34 
  35 smb_sdrc_t
  36 smb_pre_session_setup_andx(smb_request_t *sr)
  37 {
  38         smb_arg_sessionsetup_t  *sinfo;
  39         char                    *native_os;
  40         char                    *native_lm;
  41         int                     rc = 0;
  42 
  43         sinfo = smb_srm_zalloc(sr, sizeof (smb_arg_sessionsetup_t));
  44         sr->sr_ssetup = sinfo;
  45 
  46         /*
  47          * Enforce the minimum word count seen in the old protocol,
  48          * to make sure we have enough to decode the common stuff.
  49          * Further wcnt checks below.
  50          */
  51         if (sr->smb_wct < 10) {
  52                 rc = -1;
  53                 goto done;
  54         }
  55 
  56         /*
  57          * Parse common part of SMB session setup.
  58          * skip: vcnumber(2), sesskey(4)
  59          */
  60         rc = smbsr_decode_vwv(sr, "b.www6.",
  61             &sr->andx_com, &sr->andx_off,
  62             &sinfo->ssi_maxbufsize, &sinfo->ssi_maxmpxcount);
  63         if (rc != 0)
  64                 goto done;
  65 
  66         if (sr->session->dialect < NT_LM_0_12) {
  67 
  68                 sinfo->ssi_type = SMB_SSNSETUP_PRE_NTLM012;
  69                 sinfo->ssi_capabilities = 0;
  70 
  71                 rc = smbsr_decode_vwv(sr, "w4.",
  72                     &sinfo->ssi_lmpwlen);
  73                 if (rc != 0)
  74                         goto done;
  75 
  76                 sinfo->ssi_lmpwd = smb_srm_zalloc(sr, sinfo->ssi_lmpwlen + 1);
  77                 rc = smbsr_decode_data(sr, "%#c", sr, sinfo->ssi_lmpwlen,
  78                     sinfo->ssi_lmpwd);
  79                 if (rc != 0)
  80                         goto done;
  81 
  82                 sinfo->ssi_lmpwd[sinfo->ssi_lmpwlen] = 0;
  83 
  84                 if (smbsr_decode_data(sr, "%u", sr, &sinfo->ssi_user) != 0)
  85                         sinfo->ssi_user = "";
  86 
  87                 if (smbsr_decode_data(sr, "%u", sr, &sinfo->ssi_domain) != 0)
  88                         sinfo->ssi_domain = "";
  89 
  90                 goto part2;
  91         }
  92 
  93         /*
  94          * We have dialect >= NT_LM_0_12
  95          */
  96         if (sr->smb_wct == 13) {
  97                 /* Old style (non-extended) request. */
  98                 sinfo->ssi_type = SMB_SSNSETUP_NTLM012_NOEXT;
  99 
 100                 rc = smbsr_decode_vwv(sr, "ww4.l",
 101                     &sinfo->ssi_lmpwlen,
 102                     &sinfo->ssi_ntpwlen,
 103                     &sinfo->ssi_capabilities);
 104                 if (rc != 0)
 105                         goto done;
 106 
 107                 /* paranoid: ignore cap. ext. sec. here */
 108                 sinfo->ssi_capabilities &= ~CAP_EXTENDED_SECURITY;
 109 
 110                 sinfo->ssi_lmpwd = smb_srm_zalloc(sr, sinfo->ssi_lmpwlen + 1);
 111                 sinfo->ssi_ntpwd = smb_srm_zalloc(sr, sinfo->ssi_ntpwlen + 1);
 112 
 113                 rc = smbsr_decode_data(sr, "%#c#cuu", sr,
 114                     sinfo->ssi_lmpwlen, sinfo->ssi_lmpwd,
 115                     sinfo->ssi_ntpwlen, sinfo->ssi_ntpwd,
 116                     &sinfo->ssi_user, &sinfo->ssi_domain);
 117                 if (rc != 0)
 118                         goto done;
 119 
 120                 sinfo->ssi_lmpwd[sinfo->ssi_lmpwlen] = 0;
 121                 sinfo->ssi_ntpwd[sinfo->ssi_ntpwlen] = 0;
 122 
 123                 goto part2;
 124         }
 125 
 126         if (sr->smb_wct == 12) {
 127                 /* New style (extended) request. */
 128                 sinfo->ssi_type = SMB_SSNSETUP_NTLM012_EXTSEC;
 129 
 130                 rc = smbsr_decode_vwv(sr, "w4.l",
 131                     &sinfo->ssi_iseclen,
 132                     &sinfo->ssi_capabilities);
 133                 if (rc != 0)
 134                         goto done;
 135 
 136                 if ((sinfo->ssi_capabilities & CAP_EXTENDED_SECURITY) == 0) {
 137                         rc = -1;
 138                         goto done;
 139                 }
 140 
 141                 sinfo->ssi_isecblob = smb_srm_zalloc(sr, sinfo->ssi_iseclen);
 142                 rc = smbsr_decode_data(sr, "%#c", sr,
 143                     sinfo->ssi_iseclen, sinfo->ssi_isecblob);
 144                 if (rc != 0)
 145                         goto done;
 146 
 147                 goto part2;
 148         }
 149 
 150         /* Invalid message */
 151         rc = -1;
 152         goto done;
 153 
 154 part2:
 155         /*
 156          * Get the "Native OS" and "Native LanMan" strings.
 157          * These are not critical to protocol function, so
 158          * if we can't parse them, just guess "NT".
 159          * These strings are free'd with the sr.
 160          *
 161          * In NTLM 0.12, the padding between the Native OS and Native LM
 162          * is a bit strange.  On NT4.0, there is a 2 byte pad between the
 163          * OS (Windows NT 1381) and LM (Windows NT 4.0).  On Windows 2000,
 164          * there is no padding between the OS (Windows 2000 2195) and LM
 165          * (Windows 2000 5.0). If the padding is removed from the decode
 166          * string the NT4.0 LM comes out as an empty string.  So if the
 167          * client's native OS is Win NT, assume extra padding.
 168          */
 169         rc = smbsr_decode_data(sr, "%u", sr, &native_os);
 170         if (rc != 0 || native_os == NULL)
 171                 sinfo->ssi_native_os = NATIVE_OS_WINNT;
 172         else
 173                 sinfo->ssi_native_os = smbnative_os_value(native_os);
 174 
 175         if (sinfo->ssi_native_os == NATIVE_OS_WINNT)
 176                 rc = smbsr_decode_data(sr, "%,u", sr, &native_lm);
 177         else
 178                 rc = smbsr_decode_data(sr, "%u", sr, &native_lm);
 179         if (rc != 0 || native_lm == NULL)
 180                 sinfo->ssi_native_lm = NATIVE_LM_NT;
 181         else
 182                 sinfo->ssi_native_lm = smbnative_lm_value(native_lm);
 183         rc = 0;
 184 
 185 done:
 186         if (rc != 0) {
 187                 cmn_err(CE_NOTE,
 188                     "SmbSessonSetupX: client %s invalid request",
 189                     sr->session->ip_addr_str);
 190         }
 191 
 192         DTRACE_SMB_1(op__SessionSetupX__start, smb_request_t *, sr);
 193         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 194 }
 195 
 196 void
 197 smb_post_session_setup_andx(smb_request_t *sr)
 198 {
 199         smb_arg_sessionsetup_t  *sinfo = sr->sr_ssetup;
 200 
 201         DTRACE_SMB_1(op__SessionSetupX__done, smb_request_t *, sr);
 202 
 203         if (sinfo->ssi_lmpwd != NULL)
 204                 bzero(sinfo->ssi_lmpwd, sinfo->ssi_lmpwlen);
 205 
 206         if (sinfo->ssi_ntpwd != NULL)
 207                 bzero(sinfo->ssi_ntpwd, sinfo->ssi_ntpwlen);
 208 }
 209 
 210 /*
 211  *
 212  * NT systems use different native OS and native LanMan values dependent on
 213  * whether they are acting as a client or a server.  NT 4.0 server responds
 214  * with the following values:
 215  *
 216  *      NativeOS:       Windows NT 4.0
 217  *      NativeLM:       NT LAN Manager 4.0
 218  */
 219 smb_sdrc_t
 220 smb_com_session_setup_andx(smb_request_t *sr)
 221 {
 222         smb_arg_sessionsetup_t  *sinfo = sr->sr_ssetup;
 223         uint32_t                status;
 224         uint16_t                action;
 225         int                     rc;
 226 
 227         /*
 228          * Some stuff we do only in the first in a (possible)
 229          * sequence of session setup requests.
 230          */
 231         if (sinfo->ssi_type != SMB_SSNSETUP_NTLM012_EXTSEC ||
 232             sr->smb_uid == 0 || sr->smb_uid == 0xFFFF) {
 233 
 234                 /* This is a first (or only) call */
 235                 sr->session->smb_msg_size = sinfo->ssi_maxbufsize;
 236                 sr->session->smb_max_mpx = sinfo->ssi_maxmpxcount;
 237                 sr->session->capabilities = sinfo->ssi_capabilities;
 238 
 239                 if (!smb_oplock_levelII)
 240                         sr->session->capabilities &= ~CAP_LEVEL_II_OPLOCKS;
 241 
 242                 sr->session->native_os = sinfo->ssi_native_os;
 243                 sr->session->native_lm = sinfo->ssi_native_lm;
 244         }
 245 
 246         /* RejectUnencryptedAccess precludes SMB1 access */
 247         if (sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED) {
 248                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 249                     ERRDOS, ERROR_ACCESS_DENIED);
 250                 return (SDRC_ERROR);
 251         }
 252 
 253         /*
 254          * The "meat" of authentication happens here.
 255          */
 256         if (sinfo->ssi_type == SMB_SSNSETUP_NTLM012_EXTSEC)
 257                 status = smb_authenticate_ext(sr);
 258         else
 259                 status = smb_authenticate_old(sr);
 260 
 261         switch (status) {
 262 
 263         case NT_STATUS_SUCCESS:
 264                 break;
 265 
 266         /*
 267          * This is not really an error, but tells the client
 268          * it should send another session setup request.
 269          */
 270         case NT_STATUS_MORE_PROCESSING_REQUIRED:
 271                 smbsr_error(sr, status, 0, 0);
 272                 break;
 273 
 274         case NT_STATUS_ACCESS_DENIED:
 275                 smbsr_error(sr, status, ERRDOS, ERROR_ACCESS_DENIED);
 276                 return (SDRC_ERROR);
 277 
 278         case NT_STATUS_TOO_MANY_SESSIONS:
 279                 smbsr_error(sr, status, ERRSRV, ERRtoomanyuids);
 280                 return (SDRC_ERROR);
 281 
 282         case NT_STATUS_NO_LOGON_SERVERS:
 283                 smbsr_error(sr, status, ERRDOS, ERROR_NO_LOGON_SERVERS);
 284                 return (SDRC_ERROR);
 285 
 286         case NT_STATUS_NETLOGON_NOT_STARTED:
 287                 smbsr_error(sr, status, ERRDOS, ERROR_NETLOGON_NOT_STARTED);
 288                 return (SDRC_ERROR);
 289 
 290         case NT_STATUS_USER_SESSION_DELETED:
 291                 smbsr_error(sr, status, ERRSRV, ERRbaduid);
 292                 return (SDRC_ERROR);
 293 
 294         case NT_STATUS_INSUFF_SERVER_RESOURCES:
 295                 smbsr_error(sr, status, ERRSRV, ERRnoresource);
 296                 return (SDRC_ERROR);
 297 
 298         case NT_STATUS_INTERNAL_ERROR:
 299         default:
 300                 smbsr_error(sr, status, ERRSRV, ERRsrverror);
 301                 return (SDRC_ERROR);
 302 
 303         }
 304 
 305         action = SMB_USER_IS_GUEST(sr->uid_user) ? 1 : 0;
 306 
 307         switch (sinfo->ssi_type) {
 308 
 309         default:
 310         case SMB_SSNSETUP_PRE_NTLM012:
 311         case SMB_SSNSETUP_NTLM012_NOEXT:
 312 
 313                 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu",
 314                     3,
 315                     sr->andx_com,
 316                     -1,                 /* andx_off */
 317                     action,
 318                     VAR_BCC,
 319                     sr,
 320                     sr->sr_cfg->skc_native_os,
 321                     sr->sr_cfg->skc_native_lm,
 322                     sr->sr_cfg->skc_nbdomain);
 323                 break;
 324 
 325         case SMB_SSNSETUP_NTLM012_EXTSEC:
 326 
 327                 rc = smbsr_encode_result(sr, 4, VAR_BCC, "bb.wwww%#cuuu",
 328                     4,
 329                     sr->andx_com,
 330                     -1,                 /* andx_off */
 331                     action,
 332                     sinfo->ssi_oseclen,
 333                     VAR_BCC,
 334                     sr,
 335                     sinfo->ssi_oseclen,
 336                     sinfo->ssi_osecblob,
 337                     sr->sr_cfg->skc_native_os,
 338                     sr->sr_cfg->skc_native_lm,
 339                     sr->sr_cfg->skc_nbdomain);
 340                 break;
 341         }
 342 
 343         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 344 }