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 *
smb_cred_create(smb_token_t * token)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
smb_cred_set_sid(smb_id_t * id,ksid_t * ksid)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 *
smb_cred_set_sidlist(smb_ids_t * token_grps)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