1*12b65585SGordon Ross /* 2*12b65585SGordon Ross * CDDL HEADER START 3*12b65585SGordon Ross * 4*12b65585SGordon Ross * The contents of this file are subject to the terms of the 5*12b65585SGordon Ross * Common Development and Distribution License (the "License"). 6*12b65585SGordon Ross * You may not use this file except in compliance with the License. 7*12b65585SGordon Ross * 8*12b65585SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*12b65585SGordon Ross * or http://www.opensolaris.org/os/licensing. 10*12b65585SGordon Ross * See the License for the specific language governing permissions 11*12b65585SGordon Ross * and limitations under the License. 12*12b65585SGordon Ross * 13*12b65585SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 14*12b65585SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*12b65585SGordon Ross * If applicable, add the following below this CDDL HEADER, with the 16*12b65585SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 17*12b65585SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 18*12b65585SGordon Ross * 19*12b65585SGordon Ross * CDDL HEADER END 20*12b65585SGordon Ross */ 21*12b65585SGordon Ross /* 22*12b65585SGordon Ross * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23*12b65585SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 24*12b65585SGordon Ross */ 25*12b65585SGordon Ross 26*12b65585SGordon Ross /* 27*12b65585SGordon Ross * Authentication helpers for building credentials 28*12b65585SGordon Ross */ 29*12b65585SGordon Ross 30*12b65585SGordon Ross #include <sys/types.h> 31*12b65585SGordon Ross #include <sys/sid.h> 32*12b65585SGordon Ross #include <sys/priv_names.h> 33*12b65585SGordon Ross #include <sys/socket.h> 34*12b65585SGordon Ross #include <sys/un.h> 35*12b65585SGordon Ross #include <netinet/in.h> 36*12b65585SGordon Ross #include <smbsrv/smb_idmap.h> 37*12b65585SGordon Ross #include <smbsrv/smb_kproto.h> 38*12b65585SGordon Ross #include <smbsrv/smb_token.h> 39*12b65585SGordon Ross 40*12b65585SGordon Ross static void smb_cred_set_sid(smb_id_t *id, ksid_t *ksid); 41*12b65585SGordon Ross static ksidlist_t *smb_cred_set_sidlist(smb_ids_t *token_grps); 42*12b65585SGordon Ross 43*12b65585SGordon Ross /* 44*12b65585SGordon Ross * Allocate a Solaris cred and initialize it based on the access token. 45*12b65585SGordon Ross * 46*12b65585SGordon Ross * If the user can be mapped to a non-ephemeral ID, the cred gid is set 47*12b65585SGordon Ross * to the Solaris user's primary group. 48*12b65585SGordon Ross * 49*12b65585SGordon Ross * If the mapped UID is ephemeral, or the primary group could not be 50*12b65585SGordon Ross * obtained, the cred gid is set to whatever Solaris group is mapped 51*12b65585SGordon Ross * to the token's primary group. 52*12b65585SGordon Ross */ 53*12b65585SGordon Ross cred_t * 54*12b65585SGordon Ross smb_cred_create(smb_token_t *token) 55*12b65585SGordon Ross { 56*12b65585SGordon Ross ksid_t ksid; 57*12b65585SGordon Ross ksidlist_t *ksidlist = NULL; 58*12b65585SGordon Ross smb_posix_grps_t *posix_grps; 59*12b65585SGordon Ross cred_t *cr; 60*12b65585SGordon Ross gid_t gid; 61*12b65585SGordon Ross 62*12b65585SGordon Ross ASSERT(token); 63*12b65585SGordon Ross ASSERT(token->tkn_posix_grps); 64*12b65585SGordon Ross posix_grps = token->tkn_posix_grps; 65*12b65585SGordon Ross 66*12b65585SGordon Ross cr = crget(); 67*12b65585SGordon Ross ASSERT(cr != NULL); 68*12b65585SGordon Ross 69*12b65585SGordon Ross if (!IDMAP_ID_IS_EPHEMERAL(token->tkn_user.i_id) && 70*12b65585SGordon Ross (posix_grps->pg_ngrps != 0)) { 71*12b65585SGordon Ross gid = posix_grps->pg_grps[0]; 72*12b65585SGordon Ross } else { 73*12b65585SGordon Ross gid = token->tkn_primary_grp.i_id; 74*12b65585SGordon Ross } 75*12b65585SGordon Ross 76*12b65585SGordon Ross if (crsetugid(cr, token->tkn_user.i_id, gid) != 0) { 77*12b65585SGordon Ross crfree(cr); 78*12b65585SGordon Ross return (NULL); 79*12b65585SGordon Ross } 80*12b65585SGordon Ross 81*12b65585SGordon Ross if (crsetgroups(cr, posix_grps->pg_ngrps, posix_grps->pg_grps) != 0) { 82*12b65585SGordon Ross crfree(cr); 83*12b65585SGordon Ross return (NULL); 84*12b65585SGordon Ross } 85*12b65585SGordon Ross 86*12b65585SGordon Ross smb_cred_set_sid(&token->tkn_user, &ksid); 87*12b65585SGordon Ross crsetsid(cr, &ksid, KSID_USER); 88*12b65585SGordon Ross smb_cred_set_sid(&token->tkn_primary_grp, &ksid); 89*12b65585SGordon Ross crsetsid(cr, &ksid, KSID_GROUP); 90*12b65585SGordon Ross smb_cred_set_sid(&token->tkn_owner, &ksid); 91*12b65585SGordon Ross crsetsid(cr, &ksid, KSID_OWNER); 92*12b65585SGordon Ross ksidlist = smb_cred_set_sidlist(&token->tkn_win_grps); 93*12b65585SGordon Ross crsetsidlist(cr, ksidlist); 94*12b65585SGordon Ross 95*12b65585SGordon Ross /* 96*12b65585SGordon Ross * In the AD world, "take ownership privilege" is very much 97*12b65585SGordon Ross * like having Unix "root" privileges. It's normally given 98*12b65585SGordon Ross * to members of the "Administrators" group, which normally 99*12b65585SGordon Ross * includes the the local Administrator (like root) and when 100*12b65585SGordon Ross * joined to a domain, "Domain Admins". 101*12b65585SGordon Ross */ 102*12b65585SGordon Ross if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) { 103*12b65585SGordon Ross (void) crsetpriv(cr, 104*12b65585SGordon Ross PRIV_FILE_CHOWN, 105*12b65585SGordon Ross PRIV_FILE_DAC_READ, 106*12b65585SGordon Ross PRIV_FILE_DAC_SEARCH, 107*12b65585SGordon Ross PRIV_FILE_DAC_WRITE, 108*12b65585SGordon Ross PRIV_FILE_OWNER, 109*12b65585SGordon Ross NULL); 110*12b65585SGordon Ross } 111*12b65585SGordon Ross 112*12b65585SGordon Ross return (cr); 113*12b65585SGordon Ross } 114*12b65585SGordon Ross 115*12b65585SGordon Ross /* 116*12b65585SGordon Ross * Initialize the ksid based on the given smb_id_t. 117*12b65585SGordon Ross */ 118*12b65585SGordon Ross static void 119*12b65585SGordon Ross smb_cred_set_sid(smb_id_t *id, ksid_t *ksid) 120*12b65585SGordon Ross { 121*12b65585SGordon Ross char sidstr[SMB_SID_STRSZ]; 122*12b65585SGordon Ross int rc; 123*12b65585SGordon Ross 124*12b65585SGordon Ross ASSERT(id); 125*12b65585SGordon Ross ASSERT(id->i_sid); 126*12b65585SGordon Ross 127*12b65585SGordon Ross ksid->ks_id = id->i_id; 128*12b65585SGordon Ross smb_sid_tostr(id->i_sid, sidstr); 129*12b65585SGordon Ross rc = smb_sid_splitstr(sidstr, &ksid->ks_rid); 130*12b65585SGordon Ross ASSERT(rc == 0); 131*12b65585SGordon Ross 132*12b65585SGordon Ross ksid->ks_attr = id->i_attrs; 133*12b65585SGordon Ross ksid->ks_domain = ksid_lookupdomain(sidstr); 134*12b65585SGordon Ross } 135*12b65585SGordon Ross 136*12b65585SGordon Ross /* 137*12b65585SGordon Ross * Allocate and initialize the ksidlist based on the access token group list. 138*12b65585SGordon Ross */ 139*12b65585SGordon Ross static ksidlist_t * 140*12b65585SGordon Ross smb_cred_set_sidlist(smb_ids_t *token_grps) 141*12b65585SGordon Ross { 142*12b65585SGordon Ross int i; 143*12b65585SGordon Ross ksidlist_t *lp; 144*12b65585SGordon Ross 145*12b65585SGordon Ross lp = kmem_zalloc(KSIDLIST_MEM(token_grps->i_cnt), KM_SLEEP); 146*12b65585SGordon Ross lp->ksl_ref = 1; 147*12b65585SGordon Ross lp->ksl_nsid = token_grps->i_cnt; 148*12b65585SGordon Ross lp->ksl_neid = 0; 149*12b65585SGordon Ross 150*12b65585SGordon Ross for (i = 0; i < lp->ksl_nsid; i++) { 151*12b65585SGordon Ross smb_cred_set_sid(&token_grps->i_ids[i], &lp->ksl_sids[i]); 152*12b65585SGordon Ross if (lp->ksl_sids[i].ks_id > IDMAP_WK__MAX_GID) 153*12b65585SGordon Ross lp->ksl_neid++; 154*12b65585SGordon Ross } 155*12b65585SGordon Ross 156*12b65585SGordon Ross return (lp); 157*12b65585SGordon Ross } 158