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 2014 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_2(op__SessionSetupX__start, smb_request_t *, sr, 193 smb_arg_sessionsetup_t, sinfo); 194 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 195 } 196 197 void 198 smb_post_session_setup_andx(smb_request_t *sr) 199 { 200 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup; 201 202 DTRACE_SMB_2(op__SessionSetupX__done, smb_request_t *, sr, 203 smb_arg_sessionsetup_t, sinfo); 204 205 if (sinfo->ssi_lmpwd != NULL) 206 bzero(sinfo->ssi_lmpwd, sinfo->ssi_lmpwlen); 207 208 if (sinfo->ssi_ntpwd != NULL) 209 bzero(sinfo->ssi_ntpwd, sinfo->ssi_ntpwlen); 210 } 211 212 /* 213 * 214 * NT systems use different native OS and native LanMan values dependent on 215 * whether they are acting as a client or a server. NT 4.0 server responds 216 * with the following values: 217 * 218 * NativeOS: Windows NT 4.0 219 * NativeLM: NT LAN Manager 4.0 220 */ 221 smb_sdrc_t 222 smb_com_session_setup_andx(smb_request_t *sr) 223 { 224 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup; 225 uint32_t status; 226 uint16_t action; 227 int rc; 228 229 /* 230 * Some stuff we do only in the first in a (possible) 231 * sequence of session setup requests. 232 */ 233 if (sinfo->ssi_type != SMB_SSNSETUP_NTLM012_EXTSEC || 234 sr->smb_uid == 0 || sr->smb_uid == 0xFFFF) { 235 236 /* This is a first (or only) call */ 237 sr->session->smb_msg_size = sinfo->ssi_maxbufsize; 238 sr->session->smb_max_mpx = sinfo->ssi_maxmpxcount; 239 sr->session->capabilities = sinfo->ssi_capabilities; 240 241 if (!smb_oplock_levelII) 242 sr->session->capabilities &= ~CAP_LEVEL_II_OPLOCKS; 243 244 sr->session->native_os = sinfo->ssi_native_os; 245 sr->session->native_lm = sinfo->ssi_native_lm; 246 } 247 248 /* 249 * The "meat" of authentication happens here. 250 */ 251 if (sinfo->ssi_type == SMB_SSNSETUP_NTLM012_EXTSEC) 252 status = smb_authenticate_ext(sr); 253 else 254 status = smb_authenticate_old(sr); 255 256 switch (status) { 257 258 case NT_STATUS_SUCCESS: 259 break; 260 261 /* 262 * This is not really an error, but tells the client 263 * it should send another session setup request. 264 */ 265 case NT_STATUS_MORE_PROCESSING_REQUIRED: 266 smbsr_error(sr, status, 0, 0); 267 break; 268 269 case NT_STATUS_ACCESS_DENIED: 270 smbsr_error(sr, status, ERRDOS, ERROR_ACCESS_DENIED); 271 return (SDRC_ERROR); 272 273 case NT_STATUS_TOO_MANY_SESSIONS: 274 smbsr_error(sr, status, ERRSRV, ERRtoomanyuids); 275 return (SDRC_ERROR); 276 277 case NT_STATUS_NO_LOGON_SERVERS: 278 smbsr_error(sr, status, ERRDOS, ERROR_NO_LOGON_SERVERS); 279 return (SDRC_ERROR); 280 281 case NT_STATUS_NETLOGON_NOT_STARTED: 282 smbsr_error(sr, status, ERRDOS, ERROR_NETLOGON_NOT_STARTED); 283 return (SDRC_ERROR); 284 285 case NT_STATUS_USER_SESSION_DELETED: 286 smbsr_error(sr, status, ERRSRV, ERRbaduid); 287 return (SDRC_ERROR); 288 289 case NT_STATUS_INSUFF_SERVER_RESOURCES: 290 smbsr_error(sr, status, ERRSRV, ERRnoresource); 291 return (SDRC_ERROR); 292 293 case NT_STATUS_INTERNAL_ERROR: 294 default: 295 smbsr_error(sr, status, ERRSRV, ERRsrverror); 296 return (SDRC_ERROR); 297 } 298 299 action = SMB_USER_IS_GUEST(sr->uid_user) ? 1 : 0; 300 301 switch (sinfo->ssi_type) { 302 303 default: 304 case SMB_SSNSETUP_PRE_NTLM012: 305 case SMB_SSNSETUP_NTLM012_NOEXT: 306 307 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu", 308 3, 309 sr->andx_com, 310 -1, /* andx_off */ 311 action, 312 VAR_BCC, 313 sr, 314 sr->sr_cfg->skc_native_os, 315 sr->sr_cfg->skc_native_lm, 316 sr->sr_cfg->skc_nbdomain); 317 break; 318 319 case SMB_SSNSETUP_NTLM012_EXTSEC: 320 321 rc = smbsr_encode_result(sr, 4, VAR_BCC, "bb.wwww%#cuuu", 322 4, 323 sr->andx_com, 324 -1, /* andx_off */ 325 action, 326 sinfo->ssi_oseclen, 327 VAR_BCC, 328 sr, 329 sinfo->ssi_oseclen, 330 sinfo->ssi_osecblob, 331 sr->sr_cfg->skc_native_os, 332 sr->sr_cfg->skc_native_lm, 333 sr->sr_cfg->skc_nbdomain); 334 break; 335 } 336 337 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 338 } 339