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