xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_cred.c (revision 12b65585e720714b31036daaa2b30eb76014048e)
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