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 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/socket.h> 28 #include <netinet/in.h> 29 #include <smbsrv/smb_kproto.h> 30 #include <smbsrv/smb_token.h> 31 32 typedef struct smb_sessionsetup_info { 33 char *ssi_user; 34 char *ssi_domain; 35 char *ssi_native_os; 36 char *ssi_native_lm; 37 uint16_t ssi_cipwlen; 38 uint8_t *ssi_cipwd; 39 uint16_t ssi_cspwlen; 40 uint8_t *ssi_cspwd; 41 uint16_t ssi_maxbufsize; 42 uint16_t ssi_maxmpxcount; 43 uint16_t ssi_vcnumber; 44 uint32_t ssi_capabilities; 45 uint32_t ssi_sesskey; 46 } smb_sessionsetup_info_t; 47 48 #define SMB_AUTH_FAILED -1 49 #define SMB_AUTH_USER 0 50 #define SMB_AUTH_GUEST 1 51 52 static int smb_authenticate(smb_request_t *, smb_sessionsetup_info_t *, 53 smb_session_key_t **); 54 55 smb_sdrc_t 56 smb_pre_session_setup_andx(smb_request_t *sr) 57 { 58 DTRACE_SMB_1(op__SessionSetupX__start, smb_request_t *, sr); 59 return (SDRC_SUCCESS); 60 } 61 62 void 63 smb_post_session_setup_andx(smb_request_t *sr) 64 { 65 DTRACE_SMB_1(op__SessionSetupX__done, smb_request_t *, sr); 66 } 67 68 smb_sdrc_t 69 smb_com_session_setup_andx(smb_request_t *sr) 70 { 71 smb_sessionsetup_info_t sinfo; 72 smb_session_key_t *session_key = NULL; 73 char ipaddr_buf[INET6_ADDRSTRLEN]; 74 int native_lm; 75 int auth_res; 76 int rc; 77 78 bzero(&sinfo, sizeof (smb_sessionsetup_info_t)); 79 80 if (sr->session->dialect >= NT_LM_0_12) { 81 rc = smbsr_decode_vwv(sr, "b.wwwwlww4.l", &sr->andx_com, 82 &sr->andx_off, &sinfo.ssi_maxbufsize, 83 &sinfo.ssi_maxmpxcount, &sinfo.ssi_vcnumber, 84 &sinfo.ssi_sesskey, &sinfo.ssi_cipwlen, 85 &sinfo.ssi_cspwlen, &sinfo.ssi_capabilities); 86 87 if (rc != 0) 88 return (SDRC_ERROR); 89 90 sinfo.ssi_cipwd = smb_srm_zalloc(sr, sinfo.ssi_cipwlen + 1); 91 sinfo.ssi_cspwd = smb_srm_zalloc(sr, sinfo.ssi_cspwlen + 1); 92 93 /* 94 * The padding between the Native OS and Native LM is a 95 * bit strange. On NT4.0, there is a 2 byte pad between 96 * the OS (Windows NT 1381) and LM (Windows NT 4.0). 97 * On Windows 2000, there is no padding between the OS 98 * (Windows 2000 2195) and LM (Windows 2000 5.0). 99 * 100 * If the padding is removed from this decode string 101 * the NT4.0 LM comes out as an empty string. 102 * 103 * So if the client's native OS is Win NT we consider 104 * the padding otherwise we don't. 105 */ 106 rc = smbsr_decode_data(sr, "%#c#cuuu", 107 sr, 108 sinfo.ssi_cipwlen, sinfo.ssi_cipwd, 109 sinfo.ssi_cspwlen, sinfo.ssi_cspwd, 110 &sinfo.ssi_user, 111 &sinfo.ssi_domain, 112 &sinfo.ssi_native_os); 113 114 if (rc != 0) 115 return (SDRC_ERROR); 116 117 sinfo.ssi_cipwd[sinfo.ssi_cipwlen] = 0; 118 sinfo.ssi_cspwd[sinfo.ssi_cspwlen] = 0; 119 120 sr->session->native_os = 121 smbnative_os_value(sinfo.ssi_native_os); 122 123 if (sr->session->native_os == NATIVE_OS_WINNT) 124 rc = smbsr_decode_data(sr, "%,u", sr, 125 &sinfo.ssi_native_lm); 126 else 127 rc = smbsr_decode_data(sr, "%u", sr, 128 &sinfo.ssi_native_lm); 129 130 /* 131 * If the Native Lanman cannot be determined, 132 * default to Windows NT. 133 */ 134 if (rc != 0 || sinfo.ssi_native_lm == NULL) 135 sinfo.ssi_native_lm = "NT LAN Manager 4.0"; 136 } else { 137 rc = smbsr_decode_vwv(sr, "b.wwwwlw4.", &sr->andx_com, 138 &sr->andx_off, &sinfo.ssi_maxbufsize, 139 &sinfo.ssi_maxmpxcount, 140 &sinfo.ssi_vcnumber, &sinfo.ssi_sesskey, 141 &sinfo.ssi_cipwlen); 142 143 if (rc != 0) 144 return (SDRC_ERROR); 145 146 sinfo.ssi_cipwd = smb_srm_zalloc(sr, sinfo.ssi_cipwlen + 1); 147 rc = smbsr_decode_data(sr, "%#c", sr, sinfo.ssi_cipwlen, 148 sinfo.ssi_cipwd); 149 if (rc != 0) 150 return (SDRC_ERROR); 151 152 sinfo.ssi_cipwd[sinfo.ssi_cipwlen] = 0; 153 154 /* 155 * Despite the CIFS/1.0 spec, the rest of this message is 156 * not always present. We need to try to get the account 157 * name and the primary domain but we don't care about the 158 * the native OS or native LanMan fields. 159 */ 160 if (smbsr_decode_data(sr, "%u", sr, &sinfo.ssi_user) != 0) 161 sinfo.ssi_user = ""; 162 163 if (smbsr_decode_data(sr, "%u", sr, &sinfo.ssi_domain) != 0) 164 sinfo.ssi_domain = ""; 165 166 sr->session->native_os = NATIVE_OS_WINNT; 167 sinfo.ssi_native_lm = "NT LAN Manager 4.0"; 168 } 169 170 /* 171 * If the sinfo.ssi_vcnumber is zero, we can discard any 172 * other connections associated with this client. 173 */ 174 sr->session->vcnumber = sinfo.ssi_vcnumber; 175 if (sinfo.ssi_vcnumber == 0) 176 smb_server_reconnection_check(sr->sr_server, sr->session); 177 178 auth_res = smb_authenticate(sr, &sinfo, &session_key); 179 if (auth_res == SMB_AUTH_FAILED) 180 return (SDRC_ERROR); 181 182 native_lm = smbnative_lm_value(sinfo.ssi_native_lm); 183 if (native_lm == NATIVE_LM_WIN2000) 184 sinfo.ssi_capabilities |= CAP_LARGE_FILES | 185 CAP_LARGE_READX | CAP_LARGE_WRITEX; 186 187 sr->session->smb_msg_size = sinfo.ssi_maxbufsize; 188 sr->session->capabilities = sinfo.ssi_capabilities; 189 190 /* 191 * Check to see if SMB signing is enable, but if it is already turned 192 * on leave it. 193 * The first authenticated logon provides the MAC key and sequence 194 * numbers for signing all further session on the 195 * same network connection. 196 */ 197 if (!(sr->session->signing.flags & SMB_SIGNING_ENABLED) && 198 (sr->session->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) && 199 (sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) && 200 session_key) 201 smb_sign_init(sr, session_key, (char *)sinfo.ssi_cspwd, 202 sinfo.ssi_cspwlen); 203 204 if (!(sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) && 205 (sr->sr_cfg->skc_signing_required)) { 206 (void) smb_inet_ntop(&sr->session->ipaddr, ipaddr_buf, 207 SMB_IPSTRLEN(sr->session->ipaddr.a_family)); 208 cmn_err(CE_NOTE, 209 "SmbSessonSetupX: client %s is not capable of signing", 210 ipaddr_buf); 211 smbsr_error(sr, NT_STATUS_LOGON_FAILURE, 212 ERRDOS, ERROR_LOGON_FAILURE); 213 return (SDRC_ERROR); 214 } 215 216 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu", 217 3, 218 sr->andx_com, 219 -1, /* andx_off */ 220 (auth_res == SMB_AUTH_GUEST) ? 1 : 0, 221 VAR_BCC, 222 sr, 223 smbnative_os_str(&sr->sr_cfg->skc_version), 224 smbnative_lm_str(&sr->sr_cfg->skc_version), 225 sr->sr_cfg->skc_nbdomain); 226 227 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 228 } 229 230 /* 231 * Tries to authenticate the connected user. 232 * 233 * It first tries to see if the user has already been authenticated. 234 * If a match is found, the user structure in the session is duplicated 235 * and the function returns. Otherwise, user information is passed to 236 * smbd for authentication. If smbd can authenticate the user an access 237 * token structure is returned. A cred_t and user structure is created 238 * based on the returned access token. 239 */ 240 static int 241 smb_authenticate(smb_request_t *sr, smb_sessionsetup_info_t *sinfo, 242 smb_session_key_t **session_key) 243 { 244 char *hostname = sr->sr_cfg->skc_hostname; 245 int security = sr->sr_cfg->skc_secmode; 246 smb_token_t *usr_token = NULL; 247 smb_user_t *user = NULL; 248 smb_logon_t user_info; 249 boolean_t need_lookup = B_FALSE; 250 uint32_t privileges; 251 cred_t *cr; 252 char *buf = NULL; 253 char *p; 254 255 bzero(&user_info, sizeof (smb_logon_t)); 256 257 if ((*sinfo->ssi_user == '\0') && 258 (sinfo->ssi_cspwlen == 0) && 259 (sinfo->ssi_cipwlen == 0 || 260 (sinfo->ssi_cipwlen == 1 && *sinfo->ssi_cipwd == '\0'))) { 261 user_info.lg_e_username = "anonymous"; 262 user_info.lg_flags |= SMB_ATF_ANON; 263 } else { 264 user_info.lg_e_username = sinfo->ssi_user; 265 } 266 user_info.lg_e_domain = sinfo->ssi_domain; 267 268 /* 269 * Handle user@domain format. 270 * 271 * We need to extract the user and domain names but 272 * should keep the request data as is. This is important 273 * for some forms of authentication. 274 */ 275 if (*sinfo->ssi_domain == '\0') { 276 buf = smb_mem_strdup(sinfo->ssi_user); 277 if ((p = strchr(buf, '@')) != NULL) { 278 *p = '\0'; 279 user_info.lg_e_username = buf; 280 user_info.lg_e_domain = p + 1; 281 } 282 } 283 284 /* 285 * See if this user has already been authenticated. 286 * 287 * If no domain name is provided we cannot determine whether 288 * this is a local or domain user when server is operating 289 * in domain mode, so lookup will be done after authentication. 290 */ 291 if (security == SMB_SECMODE_WORKGRP) { 292 user = smb_session_dup_user(sr->session, hostname, 293 user_info.lg_e_username); 294 } else if (*user_info.lg_e_domain != '\0') { 295 user = smb_session_dup_user(sr->session, user_info.lg_e_domain, 296 user_info.lg_e_username); 297 } else { 298 need_lookup = B_TRUE; 299 } 300 301 if (user != NULL) { 302 sr->user_cr = user->u_cred; 303 sr->smb_uid = user->u_uid; 304 sr->uid_user = user; 305 306 smb_mem_free(buf); 307 308 return ((user->u_flags & SMB_USER_FLAG_GUEST) 309 ? SMB_AUTH_GUEST : SMB_AUTH_USER); 310 } 311 312 user_info.lg_level = NETR_NETWORK_LOGON; 313 user_info.lg_domain = sinfo->ssi_domain; 314 user_info.lg_username = sinfo->ssi_user; 315 user_info.lg_workstation = sr->session->workstation; 316 user_info.lg_clnt_ipaddr = sr->session->ipaddr; 317 user_info.lg_local_ipaddr = sr->session->local_ipaddr; 318 user_info.lg_local_port = sr->session->s_local_port; 319 user_info.lg_challenge_key.val = sr->session->challenge_key; 320 user_info.lg_challenge_key.len = sr->session->challenge_len; 321 user_info.lg_nt_password.val = sinfo->ssi_cspwd; 322 user_info.lg_nt_password.len = sinfo->ssi_cspwlen; 323 user_info.lg_lm_password.val = sinfo->ssi_cipwd; 324 user_info.lg_lm_password.len = sinfo->ssi_cipwlen; 325 user_info.lg_native_os = sr->session->native_os; 326 user_info.lg_native_lm = smbnative_lm_value(sinfo->ssi_native_lm); 327 328 DTRACE_PROBE1(smb__sessionsetup__clntinfo, smb_logon_t *, 329 &user_info); 330 331 usr_token = smb_get_token(&user_info); 332 333 smb_mem_free(buf); 334 335 if (usr_token == NULL) { 336 smbsr_error(sr, 0, ERRSRV, ERRbadpw); 337 return (SMB_AUTH_FAILED); 338 } 339 340 if (need_lookup) { 341 user = smb_session_dup_user(sr->session, 342 usr_token->tkn_domain_name, usr_token->tkn_account_name); 343 344 if (user != NULL) { 345 sr->user_cr = user->u_cred; 346 sr->smb_uid = user->u_uid; 347 sr->uid_user = user; 348 349 smb_token_free(usr_token); 350 return ((user->u_flags & SMB_USER_FLAG_GUEST) 351 ? SMB_AUTH_GUEST : SMB_AUTH_USER); 352 } 353 } 354 355 if (usr_token->tkn_session_key) { 356 *session_key = smb_srm_zalloc(sr, sizeof (smb_session_key_t)); 357 (void) memcpy(*session_key, usr_token->tkn_session_key, 358 sizeof (smb_session_key_t)); 359 } 360 361 if ((cr = smb_cred_create(usr_token, &privileges)) != NULL) { 362 user = smb_user_login(sr->session, cr, 363 usr_token->tkn_domain_name, 364 usr_token->tkn_account_name, 365 usr_token->tkn_flags, 366 privileges, 367 usr_token->tkn_audit_sid); 368 369 smb_cred_rele(user->u_cred); 370 if (user->u_privcred) 371 smb_cred_rele(user->u_privcred); 372 } 373 374 smb_token_free(usr_token); 375 376 if (user == NULL) { 377 smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE); 378 return (SMB_AUTH_FAILED); 379 } 380 381 sr->user_cr = user->u_cred; 382 sr->smb_uid = user->u_uid; 383 sr->uid_user = user; 384 385 return ((user->u_flags & SMB_USER_FLAG_GUEST) 386 ? SMB_AUTH_GUEST : SMB_AUTH_USER); 387 } 388