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 */ 24 25 #include <sys/types.h> 26 #include <sys/sid.h> 27 #include <sys/priv_names.h> 28 #include <sys/socket.h> 29 #include <netinet/in.h> 30 #include <smbsrv/smb_idmap.h> 31 #include <smbsrv/smb_kproto.h> 32 #include <smbsrv/smb_token.h> 33 34 static int smb_authenticate(smb_request_t *, smb_arg_sessionsetup_t *, 35 smb_session_key_t **); 36 static int smb_authenticate_core(smb_request_t *, smb_arg_sessionsetup_t *, 37 smb_session_key_t **); 38 static cred_t *smb_cred_create(smb_token_t *); 39 static void smb_cred_set_sid(smb_id_t *id, ksid_t *ksid); 40 static ksidlist_t *smb_cred_set_sidlist(smb_ids_t *token_grps); 41 static uint32_t smb_priv_xlate(smb_token_t *); 42 43 /* 44 * In NTLM 0.12, the padding between the Native OS and Native LM is a bit 45 * strange. On NT4.0, there is a 2 byte pad between the OS (Windows NT 1381) 46 * and LM (Windows NT 4.0). On Windows 2000, there is no padding between 47 * the OS (Windows 2000 2195) and LM (Windows 2000 5.0). 48 * If the padding is removed from the decode string the NT4.0 LM comes out 49 * as an empty string. So if the client's native OS is Win NT we consider 50 * the padding otherwise we don't. 51 * 52 * For Pre-NTLM 0.12, despite the CIFS/1.0 spec, the user and domain are 53 * not always present in the message. We try to get the account name and 54 * the primary domain but we don't care about the the native OS or native 55 * LM fields. 56 * 57 * If the Native LM cannot be determined, default to Windows NT. 58 */ 59 smb_sdrc_t 60 smb_pre_session_setup_andx(smb_request_t *sr) 61 { 62 smb_arg_sessionsetup_t *sinfo; 63 char *native_os; 64 char *native_lm; 65 uint16_t maxbufsize; 66 uint16_t vcnumber; 67 int rc = 0; 68 69 sinfo = smb_srm_zalloc(sr, sizeof (smb_arg_sessionsetup_t)); 70 sr->sr_ssetup = sinfo; 71 72 if (sr->session->dialect >= NT_LM_0_12) { 73 rc = smbsr_decode_vwv(sr, "b.wwwwlww4.l", &sr->andx_com, 74 &sr->andx_off, &maxbufsize, 75 &sinfo->ssi_maxmpxcount, &vcnumber, 76 &sinfo->ssi_sesskey, &sinfo->ssi_cipwlen, 77 &sinfo->ssi_cspwlen, &sinfo->ssi_capabilities); 78 if (rc != 0) 79 goto pre_session_setup_andx_done; 80 81 sinfo->ssi_cipwd = smb_srm_zalloc(sr, sinfo->ssi_cipwlen + 1); 82 sinfo->ssi_cspwd = smb_srm_zalloc(sr, sinfo->ssi_cspwlen + 1); 83 84 rc = smbsr_decode_data(sr, "%#c#cuuu", 85 sr, 86 sinfo->ssi_cipwlen, sinfo->ssi_cipwd, 87 sinfo->ssi_cspwlen, sinfo->ssi_cspwd, 88 &sinfo->ssi_user, 89 &sinfo->ssi_domain, 90 &native_os); 91 if (rc != 0) 92 goto pre_session_setup_andx_done; 93 94 sinfo->ssi_cipwd[sinfo->ssi_cipwlen] = 0; 95 sinfo->ssi_cspwd[sinfo->ssi_cspwlen] = 0; 96 97 sr->session->native_os = smbnative_os_value(native_os); 98 99 if (sr->session->native_os == NATIVE_OS_WINNT) 100 rc = smbsr_decode_data(sr, "%,u", sr, &native_lm); 101 else 102 rc = smbsr_decode_data(sr, "%u", sr, &native_lm); 103 104 if (rc != 0 || native_lm == NULL) 105 native_lm = "NT LAN Manager 4.0"; 106 107 sr->session->native_lm = smbnative_lm_value(native_lm); 108 } else { 109 rc = smbsr_decode_vwv(sr, "b.wwwwlw4.", &sr->andx_com, 110 &sr->andx_off, &maxbufsize, 111 &sinfo->ssi_maxmpxcount, &vcnumber, 112 &sinfo->ssi_sesskey, &sinfo->ssi_cipwlen); 113 if (rc != 0) 114 goto pre_session_setup_andx_done; 115 116 sinfo->ssi_cipwd = smb_srm_zalloc(sr, sinfo->ssi_cipwlen + 1); 117 rc = smbsr_decode_data(sr, "%#c", sr, sinfo->ssi_cipwlen, 118 sinfo->ssi_cipwd); 119 if (rc != 0) 120 goto pre_session_setup_andx_done; 121 122 sinfo->ssi_cipwd[sinfo->ssi_cipwlen] = 0; 123 124 if (smbsr_decode_data(sr, "%u", sr, &sinfo->ssi_user) != 0) 125 sinfo->ssi_user = ""; 126 127 if (smbsr_decode_data(sr, "%u", sr, &sinfo->ssi_domain) != 0) 128 sinfo->ssi_domain = ""; 129 130 native_lm = "NT LAN Manager 4.0"; 131 sr->session->native_os = NATIVE_OS_WINNT; 132 sr->session->native_lm = smbnative_lm_value(native_lm); 133 } 134 135 sr->session->vcnumber = vcnumber; 136 sr->session->smb_msg_size = maxbufsize; 137 138 pre_session_setup_andx_done: 139 DTRACE_SMB_2(op__SessionSetupX__start, smb_request_t *, sr, 140 smb_arg_sessionsetup_t, sinfo); 141 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 142 } 143 144 void 145 smb_post_session_setup_andx(smb_request_t *sr) 146 { 147 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup; 148 149 DTRACE_SMB_2(op__SessionSetupX__done, smb_request_t *, sr, 150 smb_arg_sessionsetup_t, sinfo); 151 152 if (sinfo->ssi_cipwd != NULL) 153 bzero(sinfo->ssi_cipwd, sinfo->ssi_cipwlen + 1); 154 155 if (sinfo->ssi_cspwd != NULL) 156 bzero(sinfo->ssi_cspwd, sinfo->ssi_cspwlen + 1); 157 } 158 159 /* 160 * If the vcnumber is zero, discard any other connections associated with 161 * this client. 162 * 163 * If signing has not already been enabled on this session check to see if 164 * it should be enabled. The first authenticated logon provides the MAC 165 * key and sequence numbers for signing all subsequent sessions on the same 166 * connection. 167 * 168 * NT systems use different native OS and native LanMan values dependent on 169 * whether they are acting as a client or a server. NT 4.0 server responds 170 * with the following values: 171 * 172 * NativeOS: Windows NT 4.0 173 * NativeLM: NT LAN Manager 4.0 174 */ 175 smb_sdrc_t 176 smb_com_session_setup_andx(smb_request_t *sr) 177 { 178 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup; 179 smb_session_key_t *session_key = NULL; 180 char ipaddr_buf[INET6_ADDRSTRLEN]; 181 int rc; 182 183 if (sr->session->vcnumber == 0) 184 smb_server_reconnection_check(sr->sr_server, sr->session); 185 186 if (smb_authenticate(sr, sinfo, &session_key) != 0) 187 return (SDRC_ERROR); 188 189 if (sr->session->native_lm == NATIVE_LM_WIN2000) 190 sinfo->ssi_capabilities |= CAP_LARGE_FILES | 191 CAP_LARGE_READX | CAP_LARGE_WRITEX; 192 193 if (!smb_oplock_levelII) 194 sr->session->capabilities &= ~CAP_LEVEL_II_OPLOCKS; 195 196 sr->session->capabilities = sinfo->ssi_capabilities; 197 198 if (!(sr->session->signing.flags & SMB_SIGNING_ENABLED) && 199 (sr->session->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) && 200 (sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) && 201 session_key) 202 smb_sign_init(sr, session_key, (char *)sinfo->ssi_cspwd, 203 sinfo->ssi_cspwlen); 204 205 if (!(sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) && 206 (sr->sr_cfg->skc_signing_required)) { 207 (void) smb_inet_ntop(&sr->session->ipaddr, ipaddr_buf, 208 SMB_IPSTRLEN(sr->session->ipaddr.a_family)); 209 cmn_err(CE_NOTE, 210 "SmbSessonSetupX: client %s does not support signing", 211 ipaddr_buf); 212 smbsr_error(sr, NT_STATUS_LOGON_FAILURE, 213 ERRDOS, ERROR_LOGON_FAILURE); 214 return (SDRC_ERROR); 215 } 216 217 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu", 218 3, 219 sr->andx_com, 220 -1, /* andx_off */ 221 sinfo->ssi_guest ? 1 : 0, 222 VAR_BCC, 223 sr, 224 smbnative_os_str(&sr->sr_cfg->skc_version), 225 smbnative_lm_str(&sr->sr_cfg->skc_version), 226 sr->sr_cfg->skc_nbdomain); 227 228 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 229 } 230 231 static int 232 smb_authenticate(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo, 233 smb_session_key_t **session_key) 234 { 235 int rc; 236 smb_server_t *sv = sr->sr_server; 237 238 if (smb_threshold_enter(&sv->sv_ssetup_ct) != 0) { 239 smbsr_error(sr, RPC_NT_SERVER_TOO_BUSY, 0, 0); 240 return (-1); 241 } 242 243 rc = smb_authenticate_core(sr, sinfo, session_key); 244 smb_threshold_exit(&sv->sv_ssetup_ct, sv); 245 return (rc); 246 } 247 248 /* 249 * Authenticate a user. If the user has already been authenticated on 250 * this session, we can simply dup the user and return. 251 * 252 * Otherwise, the user information is passed to smbd for authentication. 253 * If smbd can authenticate the user an access token is returned and we 254 * generate a cred and new user based on the token. 255 */ 256 static int 257 smb_authenticate_core(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo, 258 smb_session_key_t **session_key) 259 { 260 char *hostname = sr->sr_cfg->skc_hostname; 261 int security = sr->sr_cfg->skc_secmode; 262 smb_token_t *token = NULL; 263 smb_user_t *user = NULL; 264 smb_logon_t user_info; 265 boolean_t need_lookup = B_FALSE; 266 uint32_t privileges; 267 cred_t *cr; 268 char *buf = NULL; 269 char *p; 270 271 bzero(&user_info, sizeof (smb_logon_t)); 272 user_info.lg_e_domain = sinfo->ssi_domain; 273 274 if ((*sinfo->ssi_user == '\0') && 275 (sinfo->ssi_cspwlen == 0) && 276 (sinfo->ssi_cipwlen == 0 || 277 (sinfo->ssi_cipwlen == 1 && *sinfo->ssi_cipwd == '\0'))) { 278 user_info.lg_e_username = "anonymous"; 279 user_info.lg_flags |= SMB_ATF_ANON; 280 } else { 281 user_info.lg_e_username = sinfo->ssi_user; 282 } 283 284 /* 285 * Handle user@domain format. We need to retain the original 286 * data as this is important in some forms of authentication. 287 */ 288 if (*sinfo->ssi_domain == '\0') { 289 buf = smb_srm_strdup(sr, sinfo->ssi_user); 290 if ((p = strchr(buf, '@')) != NULL) { 291 *p = '\0'; 292 user_info.lg_e_username = buf; 293 user_info.lg_e_domain = p + 1; 294 } 295 } 296 297 /* 298 * If no domain name has been provided in domain mode we cannot 299 * determine if this is a local user or a domain user without 300 * obtaining an access token. So we postpone the lookup until 301 * after authentication. 302 */ 303 if (security == SMB_SECMODE_WORKGRP) { 304 user = smb_session_dup_user(sr->session, hostname, 305 user_info.lg_e_username); 306 } else if (*user_info.lg_e_domain != '\0') { 307 user = smb_session_dup_user(sr->session, user_info.lg_e_domain, 308 user_info.lg_e_username); 309 } else { 310 need_lookup = B_TRUE; 311 } 312 313 if (user != NULL) { 314 sinfo->ssi_guest = SMB_USER_IS_GUEST(user); 315 sr->user_cr = user->u_cred; 316 sr->smb_uid = user->u_uid; 317 sr->uid_user = user; 318 return (0); 319 } 320 321 user_info.lg_level = NETR_NETWORK_LOGON; 322 user_info.lg_domain = sinfo->ssi_domain; 323 user_info.lg_username = sinfo->ssi_user; 324 user_info.lg_workstation = sr->session->workstation; 325 user_info.lg_clnt_ipaddr = sr->session->ipaddr; 326 user_info.lg_local_ipaddr = sr->session->local_ipaddr; 327 user_info.lg_local_port = sr->session->s_local_port; 328 user_info.lg_challenge_key.val = sr->session->challenge_key; 329 user_info.lg_challenge_key.len = sr->session->challenge_len; 330 user_info.lg_nt_password.val = sinfo->ssi_cspwd; 331 user_info.lg_nt_password.len = sinfo->ssi_cspwlen; 332 user_info.lg_lm_password.val = sinfo->ssi_cipwd; 333 user_info.lg_lm_password.len = sinfo->ssi_cipwlen; 334 user_info.lg_native_os = sr->session->native_os; 335 user_info.lg_native_lm = sr->session->native_lm; 336 337 DTRACE_PROBE1(smb__sessionsetup__clntinfo, smb_logon_t *, &user_info); 338 339 if ((token = smb_get_token(&user_info)) == NULL) { 340 smbsr_error(sr, 0, ERRSRV, ERRbadpw); 341 return (-1); 342 } 343 344 if (need_lookup) { 345 user = smb_session_dup_user(sr->session, 346 token->tkn_domain_name, token->tkn_account_name); 347 if (user != NULL) { 348 sinfo->ssi_guest = SMB_USER_IS_GUEST(user); 349 sr->user_cr = user->u_cred; 350 sr->smb_uid = user->u_uid; 351 sr->uid_user = user; 352 smb_token_free(token); 353 return (0); 354 } 355 } 356 357 if (token->tkn_session_key) { 358 *session_key = smb_srm_zalloc(sr, sizeof (smb_session_key_t)); 359 bcopy(token->tkn_session_key, *session_key, 360 sizeof (smb_session_key_t)); 361 } 362 363 if ((cr = smb_cred_create(token)) == NULL) { 364 smb_token_free(token); 365 smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE); 366 return (-1); 367 } 368 369 privileges = smb_priv_xlate(token); 370 371 user = smb_user_login(sr->session, cr, 372 token->tkn_domain_name, token->tkn_account_name, 373 token->tkn_flags, privileges, token->tkn_audit_sid); 374 375 crfree(cr); 376 smb_token_free(token); 377 378 if (user == NULL) { 379 smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE); 380 return (-1); 381 } 382 383 sinfo->ssi_guest = SMB_USER_IS_GUEST(user); 384 sr->user_cr = user->u_cred; 385 sr->smb_uid = user->u_uid; 386 sr->uid_user = user; 387 return (0); 388 } 389 390 /* 391 * Allocate a Solaris cred and initialize it based on the access token. 392 * 393 * If the user can be mapped to a non-ephemeral ID, the cred gid is set 394 * to the Solaris user's primary group. 395 * 396 * If the mapped UID is ephemeral, or the primary group could not be 397 * obtained, the cred gid is set to whatever Solaris group is mapped 398 * to the token's primary group. 399 */ 400 static cred_t * 401 smb_cred_create(smb_token_t *token) 402 { 403 ksid_t ksid; 404 ksidlist_t *ksidlist = NULL; 405 smb_posix_grps_t *posix_grps; 406 cred_t *cr; 407 gid_t gid; 408 409 ASSERT(token); 410 ASSERT(token->tkn_posix_grps); 411 posix_grps = token->tkn_posix_grps; 412 413 cr = crget(); 414 ASSERT(cr != NULL); 415 416 if (!IDMAP_ID_IS_EPHEMERAL(token->tkn_user.i_id) && 417 (posix_grps->pg_ngrps != 0)) { 418 gid = posix_grps->pg_grps[0]; 419 } else { 420 gid = token->tkn_primary_grp.i_id; 421 } 422 423 if (crsetugid(cr, token->tkn_user.i_id, gid) != 0) { 424 crfree(cr); 425 return (NULL); 426 } 427 428 if (crsetgroups(cr, posix_grps->pg_ngrps, posix_grps->pg_grps) != 0) { 429 crfree(cr); 430 return (NULL); 431 } 432 433 smb_cred_set_sid(&token->tkn_user, &ksid); 434 crsetsid(cr, &ksid, KSID_USER); 435 smb_cred_set_sid(&token->tkn_primary_grp, &ksid); 436 crsetsid(cr, &ksid, KSID_GROUP); 437 smb_cred_set_sid(&token->tkn_owner, &ksid); 438 crsetsid(cr, &ksid, KSID_OWNER); 439 ksidlist = smb_cred_set_sidlist(&token->tkn_win_grps); 440 crsetsidlist(cr, ksidlist); 441 442 if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) 443 (void) crsetpriv(cr, PRIV_FILE_CHOWN, NULL); 444 445 return (cr); 446 } 447 448 /* 449 * Initialize the ksid based on the given smb_id_t. 450 */ 451 static void 452 smb_cred_set_sid(smb_id_t *id, ksid_t *ksid) 453 { 454 char sidstr[SMB_SID_STRSZ]; 455 int rc; 456 457 ASSERT(id); 458 ASSERT(id->i_sid); 459 460 ksid->ks_id = id->i_id; 461 smb_sid_tostr(id->i_sid, sidstr); 462 rc = smb_sid_splitstr(sidstr, &ksid->ks_rid); 463 ASSERT(rc == 0); 464 465 ksid->ks_attr = id->i_attrs; 466 ksid->ks_domain = ksid_lookupdomain(sidstr); 467 } 468 469 /* 470 * Allocate and initialize the ksidlist based on the access token group list. 471 */ 472 static ksidlist_t * 473 smb_cred_set_sidlist(smb_ids_t *token_grps) 474 { 475 int i; 476 ksidlist_t *lp; 477 478 lp = kmem_zalloc(KSIDLIST_MEM(token_grps->i_cnt), KM_SLEEP); 479 lp->ksl_ref = 1; 480 lp->ksl_nsid = token_grps->i_cnt; 481 lp->ksl_neid = 0; 482 483 for (i = 0; i < lp->ksl_nsid; i++) { 484 smb_cred_set_sid(&token_grps->i_ids[i], &lp->ksl_sids[i]); 485 if (lp->ksl_sids[i].ks_id > IDMAP_WK__MAX_GID) 486 lp->ksl_neid++; 487 } 488 489 return (lp); 490 } 491 492 /* 493 * Convert access token privileges to local definitions. 494 */ 495 static uint32_t 496 smb_priv_xlate(smb_token_t *token) 497 { 498 uint32_t privileges = 0; 499 500 if (smb_token_query_privilege(token, SE_BACKUP_LUID)) 501 privileges |= SMB_USER_PRIV_BACKUP; 502 503 if (smb_token_query_privilege(token, SE_RESTORE_LUID)) 504 privileges |= SMB_USER_PRIV_RESTORE; 505 506 if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) 507 privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP; 508 509 if (smb_token_query_privilege(token, SE_SECURITY_LUID)) 510 privileges |= SMB_USER_PRIV_SECURITY; 511 512 return (privileges); 513 } 514