112b65585SGordon Ross /* 212b65585SGordon Ross * CDDL HEADER START 312b65585SGordon Ross * 412b65585SGordon Ross * The contents of this file are subject to the terms of the 512b65585SGordon Ross * Common Development and Distribution License (the "License"). 612b65585SGordon Ross * You may not use this file except in compliance with the License. 712b65585SGordon Ross * 812b65585SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 912b65585SGordon Ross * or http://www.opensolaris.org/os/licensing. 1012b65585SGordon Ross * See the License for the specific language governing permissions 1112b65585SGordon Ross * and limitations under the License. 1212b65585SGordon Ross * 1312b65585SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 1412b65585SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1512b65585SGordon Ross * If applicable, add the following below this CDDL HEADER, with the 1612b65585SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 1712b65585SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 1812b65585SGordon Ross * 1912b65585SGordon Ross * CDDL HEADER END 2012b65585SGordon Ross */ 2112b65585SGordon Ross /* 2212b65585SGordon Ross * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 2312b65585SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 2412b65585SGordon Ross */ 2512b65585SGordon Ross 2612b65585SGordon Ross /* 2712b65585SGordon Ross * Authentication helpers for building credentials 2812b65585SGordon Ross */ 2912b65585SGordon Ross 3012b65585SGordon Ross #include <sys/types.h> 3112b65585SGordon Ross #include <sys/sid.h> 3212b65585SGordon Ross #include <sys/priv_names.h> 3312b65585SGordon Ross #include <sys/socket.h> 3412b65585SGordon Ross #include <sys/un.h> 3512b65585SGordon Ross #include <netinet/in.h> 3612b65585SGordon Ross #include <smbsrv/smb_idmap.h> 3712b65585SGordon Ross #include <smbsrv/smb_kproto.h> 3812b65585SGordon Ross #include <smbsrv/smb_token.h> 3912b65585SGordon Ross 4012b65585SGordon Ross static void smb_cred_set_sid(smb_id_t *id, ksid_t *ksid); 4112b65585SGordon Ross static ksidlist_t *smb_cred_set_sidlist(smb_ids_t *token_grps); 4212b65585SGordon Ross 4312b65585SGordon Ross /* 4412b65585SGordon Ross * Allocate a Solaris cred and initialize it based on the access token. 4512b65585SGordon Ross * 4612b65585SGordon Ross * If the user can be mapped to a non-ephemeral ID, the cred gid is set 4712b65585SGordon Ross * to the Solaris user's primary group. 4812b65585SGordon Ross * 4912b65585SGordon Ross * If the mapped UID is ephemeral, or the primary group could not be 5012b65585SGordon Ross * obtained, the cred gid is set to whatever Solaris group is mapped 5112b65585SGordon Ross * to the token's primary group. 52*cc3780e6SGordon Ross * 53*cc3780e6SGordon Ross * Also add any privileges that should always be in effect for this user. 54*cc3780e6SGordon Ross * Note that an SMB user object also gets a u_privcred which is used 55*cc3780e6SGordon Ross * when the client opens an object with "backup/restore intent". 56*cc3780e6SGordon Ross * That cred is setup later, in smb_user_setcred(). 5712b65585SGordon Ross */ 5812b65585SGordon Ross cred_t * 5912b65585SGordon Ross smb_cred_create(smb_token_t *token) 6012b65585SGordon Ross { 6112b65585SGordon Ross ksid_t ksid; 6212b65585SGordon Ross ksidlist_t *ksidlist = NULL; 6312b65585SGordon Ross smb_posix_grps_t *posix_grps; 6412b65585SGordon Ross cred_t *cr; 6512b65585SGordon Ross gid_t gid; 6612b65585SGordon Ross 6712b65585SGordon Ross ASSERT(token); 6812b65585SGordon Ross ASSERT(token->tkn_posix_grps); 6912b65585SGordon Ross posix_grps = token->tkn_posix_grps; 7012b65585SGordon Ross 7112b65585SGordon Ross cr = crget(); 7212b65585SGordon Ross ASSERT(cr != NULL); 7312b65585SGordon Ross 7412b65585SGordon Ross if (!IDMAP_ID_IS_EPHEMERAL(token->tkn_user.i_id) && 7512b65585SGordon Ross (posix_grps->pg_ngrps != 0)) { 7612b65585SGordon Ross gid = posix_grps->pg_grps[0]; 7712b65585SGordon Ross } else { 7812b65585SGordon Ross gid = token->tkn_primary_grp.i_id; 7912b65585SGordon Ross } 8012b65585SGordon Ross 8112b65585SGordon Ross if (crsetugid(cr, token->tkn_user.i_id, gid) != 0) { 8212b65585SGordon Ross crfree(cr); 8312b65585SGordon Ross return (NULL); 8412b65585SGordon Ross } 8512b65585SGordon Ross 8612b65585SGordon Ross if (crsetgroups(cr, posix_grps->pg_ngrps, posix_grps->pg_grps) != 0) { 8712b65585SGordon Ross crfree(cr); 8812b65585SGordon Ross return (NULL); 8912b65585SGordon Ross } 9012b65585SGordon Ross 9112b65585SGordon Ross smb_cred_set_sid(&token->tkn_user, &ksid); 9212b65585SGordon Ross crsetsid(cr, &ksid, KSID_USER); 9312b65585SGordon Ross smb_cred_set_sid(&token->tkn_primary_grp, &ksid); 9412b65585SGordon Ross crsetsid(cr, &ksid, KSID_GROUP); 9512b65585SGordon Ross smb_cred_set_sid(&token->tkn_owner, &ksid); 9612b65585SGordon Ross crsetsid(cr, &ksid, KSID_OWNER); 9712b65585SGordon Ross ksidlist = smb_cred_set_sidlist(&token->tkn_win_grps); 9812b65585SGordon Ross crsetsidlist(cr, ksidlist); 9912b65585SGordon Ross 10012b65585SGordon Ross /* 10112b65585SGordon Ross * In the AD world, "take ownership privilege" is very much 10212b65585SGordon Ross * like having Unix "root" privileges. It's normally given 10312b65585SGordon Ross * to members of the "Administrators" group, which normally 10412b65585SGordon Ross * includes the the local Administrator (like root) and when 10512b65585SGordon Ross * joined to a domain, "Domain Admins". 10612b65585SGordon Ross */ 10712b65585SGordon Ross if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) { 10812b65585SGordon Ross (void) crsetpriv(cr, 10912b65585SGordon Ross PRIV_FILE_CHOWN, 11012b65585SGordon Ross PRIV_FILE_DAC_READ, 11112b65585SGordon Ross PRIV_FILE_DAC_SEARCH, 11212b65585SGordon Ross PRIV_FILE_DAC_WRITE, 11312b65585SGordon Ross PRIV_FILE_OWNER, 11412b65585SGordon Ross NULL); 11512b65585SGordon Ross } 11612b65585SGordon Ross 117*cc3780e6SGordon Ross /* 118*cc3780e6SGordon Ross * See smb.4 bypass_traverse_checking 119*cc3780e6SGordon Ross * 120*cc3780e6SGordon Ross * For historical reasons, the Windows privilege is named 121*cc3780e6SGordon Ross * SeChangeNotifyPrivilege, though the description is 122*cc3780e6SGordon Ross * "Bypass traverse checking". 123*cc3780e6SGordon Ross */ 124*cc3780e6SGordon Ross if (smb_token_query_privilege(token, SE_CHANGE_NOTIFY_LUID)) { 125*cc3780e6SGordon Ross (void) crsetpriv(cr, PRIV_FILE_DAC_SEARCH, NULL); 126*cc3780e6SGordon Ross } 127*cc3780e6SGordon Ross 128*cc3780e6SGordon Ross 12912b65585SGordon Ross return (cr); 13012b65585SGordon Ross } 13112b65585SGordon Ross 13212b65585SGordon Ross /* 13312b65585SGordon Ross * Initialize the ksid based on the given smb_id_t. 13412b65585SGordon Ross */ 13512b65585SGordon Ross static void 13612b65585SGordon Ross smb_cred_set_sid(smb_id_t *id, ksid_t *ksid) 13712b65585SGordon Ross { 13812b65585SGordon Ross char sidstr[SMB_SID_STRSZ]; 13912b65585SGordon Ross int rc; 14012b65585SGordon Ross 14112b65585SGordon Ross ASSERT(id); 14212b65585SGordon Ross ASSERT(id->i_sid); 14312b65585SGordon Ross 14412b65585SGordon Ross ksid->ks_id = id->i_id; 14512b65585SGordon Ross smb_sid_tostr(id->i_sid, sidstr); 14612b65585SGordon Ross rc = smb_sid_splitstr(sidstr, &ksid->ks_rid); 14712b65585SGordon Ross ASSERT(rc == 0); 14812b65585SGordon Ross 14912b65585SGordon Ross ksid->ks_attr = id->i_attrs; 15012b65585SGordon Ross ksid->ks_domain = ksid_lookupdomain(sidstr); 15112b65585SGordon Ross } 15212b65585SGordon Ross 15312b65585SGordon Ross /* 15412b65585SGordon Ross * Allocate and initialize the ksidlist based on the access token group list. 15512b65585SGordon Ross */ 15612b65585SGordon Ross static ksidlist_t * 15712b65585SGordon Ross smb_cred_set_sidlist(smb_ids_t *token_grps) 15812b65585SGordon Ross { 15912b65585SGordon Ross int i; 16012b65585SGordon Ross ksidlist_t *lp; 16112b65585SGordon Ross 16212b65585SGordon Ross lp = kmem_zalloc(KSIDLIST_MEM(token_grps->i_cnt), KM_SLEEP); 16312b65585SGordon Ross lp->ksl_ref = 1; 16412b65585SGordon Ross lp->ksl_nsid = token_grps->i_cnt; 16512b65585SGordon Ross lp->ksl_neid = 0; 16612b65585SGordon Ross 16712b65585SGordon Ross for (i = 0; i < lp->ksl_nsid; i++) { 16812b65585SGordon Ross smb_cred_set_sid(&token_grps->i_ids[i], &lp->ksl_sids[i]); 16912b65585SGordon Ross if (lp->ksl_sids[i].ks_id > IDMAP_WK__MAX_GID) 17012b65585SGordon Ross lp->ksl_neid++; 17112b65585SGordon Ross } 17212b65585SGordon Ross 17312b65585SGordon Ross return (lp); 17412b65585SGordon Ross } 175