112b6558Gordon Ross/*
212b6558Gordon Ross * CDDL HEADER START
312b6558Gordon Ross *
412b6558Gordon Ross * The contents of this file are subject to the terms of the
512b6558Gordon Ross * Common Development and Distribution License (the "License").
612b6558Gordon Ross * You may not use this file except in compliance with the License.
712b6558Gordon Ross *
812b6558Gordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
912b6558Gordon Ross * or http://www.opensolaris.org/os/licensing.
1012b6558Gordon Ross * See the License for the specific language governing permissions
1112b6558Gordon Ross * and limitations under the License.
1212b6558Gordon Ross *
1312b6558Gordon Ross * When distributing Covered Code, include this CDDL HEADER in each
1412b6558Gordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1512b6558Gordon Ross * If applicable, add the following below this CDDL HEADER, with the
1612b6558Gordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
1712b6558Gordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
1812b6558Gordon Ross *
1912b6558Gordon Ross * CDDL HEADER END
2012b6558Gordon Ross */
2112b6558Gordon Ross/*
2212b6558Gordon Ross * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
230292c17Matt Barden * Copyright 2019 Nexenta by DDN, Inc. All rights reserved.
2412b6558Gordon Ross */
2512b6558Gordon Ross
2612b6558Gordon Ross/*
2712b6558Gordon Ross * Authentication helpers for building credentials
2812b6558Gordon Ross */
2912b6558Gordon Ross
3012b6558Gordon Ross#include <sys/types.h>
3112b6558Gordon Ross#include <sys/sid.h>
3212b6558Gordon Ross#include <sys/priv_names.h>
3312b6558Gordon Ross#include <sys/socket.h>
3412b6558Gordon Ross#include <sys/un.h>
3512b6558Gordon Ross#include <netinet/in.h>
3612b6558Gordon Ross#include <smbsrv/smb_idmap.h>
3712b6558Gordon Ross#include <smbsrv/smb_kproto.h>
3812b6558Gordon Ross#include <smbsrv/smb_token.h>
3912b6558Gordon Ross
4012b6558Gordon Rossstatic void smb_cred_set_sid(smb_id_t *id, ksid_t *ksid);
4112b6558Gordon Rossstatic ksidlist_t *smb_cred_set_sidlist(smb_ids_t *token_grps);
4212b6558Gordon Ross
4312b6558Gordon Ross/*
4412b6558Gordon Ross * Allocate a Solaris cred and initialize it based on the access token.
4512b6558Gordon Ross *
4612b6558Gordon Ross * If the user can be mapped to a non-ephemeral ID, the cred gid is set
4712b6558Gordon Ross * to the Solaris user's primary group.
4812b6558Gordon Ross *
4912b6558Gordon Ross * If the mapped UID is ephemeral, or the primary group could not be
5012b6558Gordon Ross * obtained, the cred gid is set to whatever Solaris group is mapped
5112b6558Gordon Ross * to the token's primary group.
52cc3780eGordon Ross *
53cc3780eGordon Ross * Also add any privileges that should always be in effect for this user.
54cc3780eGordon Ross * Note that an SMB user object also gets a u_privcred which is used
55cc3780eGordon Ross * when the client opens an object with "backup/restore intent".
56cc3780eGordon Ross * That cred is setup later, in smb_user_setcred().
5712b6558Gordon Ross */
5812b6558Gordon Rosscred_t *
5912b6558Gordon Rosssmb_cred_create(smb_token_t *token)
6012b6558Gordon Ross{
6112b6558Gordon Ross	ksid_t			ksid;
6212b6558Gordon Ross	ksidlist_t		*ksidlist = NULL;
6312b6558Gordon Ross	smb_posix_grps_t	*posix_grps;
6412b6558Gordon Ross	cred_t			*cr;
6512b6558Gordon Ross	gid_t			gid;
6612b6558Gordon Ross
6712b6558Gordon Ross	ASSERT(token);
6812b6558Gordon Ross	ASSERT(token->tkn_posix_grps);
6912b6558Gordon Ross	posix_grps = token->tkn_posix_grps;
7012b6558Gordon Ross
7112b6558Gordon Ross	cr = crget();
7212b6558Gordon Ross	ASSERT(cr != NULL);
7312b6558Gordon Ross
7412b6558Gordon Ross	if (!IDMAP_ID_IS_EPHEMERAL(token->tkn_user.i_id) &&
7512b6558Gordon Ross	    (posix_grps->pg_ngrps != 0)) {
7612b6558Gordon Ross		gid = posix_grps->pg_grps[0];
7712b6558Gordon Ross	} else {
7812b6558Gordon Ross		gid = token->tkn_primary_grp.i_id;
7912b6558Gordon Ross	}
8012b6558Gordon Ross
8112b6558Gordon Ross	if (crsetugid(cr, token->tkn_user.i_id, gid) != 0) {
8212b6558Gordon Ross		crfree(cr);
8312b6558Gordon Ross		return (NULL);
8412b6558Gordon Ross	}
8512b6558Gordon Ross
8612b6558Gordon Ross	if (crsetgroups(cr, posix_grps->pg_ngrps, posix_grps->pg_grps) != 0) {
8712b6558Gordon Ross		crfree(cr);
8812b6558Gordon Ross		return (NULL);
8912b6558Gordon Ross	}
9012b6558Gordon Ross
9112b6558Gordon Ross	smb_cred_set_sid(&token->tkn_user, &ksid);
9212b6558Gordon Ross	crsetsid(cr, &ksid, KSID_USER);
9312b6558Gordon Ross	smb_cred_set_sid(&token->tkn_primary_grp, &ksid);
9412b6558Gordon Ross	crsetsid(cr, &ksid, KSID_GROUP);
9512b6558Gordon Ross	smb_cred_set_sid(&token->tkn_owner, &ksid);
9612b6558Gordon Ross	crsetsid(cr, &ksid, KSID_OWNER);
9712b6558Gordon Ross	ksidlist = smb_cred_set_sidlist(&token->tkn_win_grps);
9812b6558Gordon Ross	crsetsidlist(cr, ksidlist);
9912b6558Gordon Ross
10012b6558Gordon Ross	return (cr);
10112b6558Gordon Ross}
10212b6558Gordon Ross
10312b6558Gordon Ross/*
10412b6558Gordon Ross * Initialize the ksid based on the given smb_id_t.
10512b6558Gordon Ross */
10612b6558Gordon Rossstatic void
10712b6558Gordon Rosssmb_cred_set_sid(smb_id_t *id, ksid_t *ksid)
10812b6558Gordon Ross{
10912b6558Gordon Ross	char sidstr[SMB_SID_STRSZ];
11012b6558Gordon Ross	int rc;
11112b6558Gordon Ross
11212b6558Gordon Ross	ASSERT(id);
11312b6558Gordon Ross	ASSERT(id->i_sid);
11412b6558Gordon Ross
11512b6558Gordon Ross	ksid->ks_id = id->i_id;
11612b6558Gordon Ross	smb_sid_tostr(id->i_sid, sidstr);
11712b6558Gordon Ross	rc = smb_sid_splitstr(sidstr, &ksid->ks_rid);
11812b6558Gordon Ross	ASSERT(rc == 0);
11912b6558Gordon Ross
12012b6558Gordon Ross	ksid->ks_attr = id->i_attrs;
12112b6558Gordon Ross	ksid->ks_domain = ksid_lookupdomain(sidstr);
12212b6558Gordon Ross}
12312b6558Gordon Ross
12412b6558Gordon Ross/*
12512b6558Gordon Ross * Allocate and initialize the ksidlist based on the access token group list.
12612b6558Gordon Ross */
12712b6558Gordon Rossstatic ksidlist_t *
12812b6558Gordon Rosssmb_cred_set_sidlist(smb_ids_t *token_grps)
12912b6558Gordon Ross{
13012b6558Gordon Ross	int i;
13112b6558Gordon Ross	ksidlist_t *lp;
13212b6558Gordon Ross
13312b6558Gordon Ross	lp = kmem_zalloc(KSIDLIST_MEM(token_grps->i_cnt), KM_SLEEP);
13412b6558Gordon Ross	lp->ksl_ref = 1;
13512b6558Gordon Ross	lp->ksl_nsid = token_grps->i_cnt;
13612b6558Gordon Ross	lp->ksl_neid = 0;
13712b6558Gordon Ross
13812b6558Gordon Ross	for (i = 0; i < lp->ksl_nsid; i++) {
13912b6558Gordon Ross		smb_cred_set_sid(&token_grps->i_ids[i], &lp->ksl_sids[i]);
14012b6558Gordon Ross		if (lp->ksl_sids[i].ks_id > IDMAP_WK__MAX_GID)
14112b6558Gordon Ross			lp->ksl_neid++;
14212b6558Gordon Ross	}
14312b6558Gordon Ross
14412b6558Gordon Ross	return (lp);
14512b6558Gordon Ross}
1468d94f65Gordon Ross
1478d94f65Gordon Ross/*
1488d94f65Gordon Ross * Special variant of smb_cred_create() used when we need an
1498d94f65Gordon Ross * SMB kcred (e.g. DH import).  The returned cred must be
1508d94f65Gordon Ross * from crget() so it can be passed to smb_user_setcred().
1518d94f65Gordon Ross */
1528d94f65Gordon Rosscred_t *
1538d94f65Gordon Rosssmb_kcred_create(void)
1548d94f65Gordon Ross{
1558d94f65Gordon Ross	cred_t	*cr;
1568d94f65Gordon Ross
1578d94f65Gordon Ross	cr = crget();
1588d94f65Gordon Ross	ASSERT(cr != NULL);
1598d94f65Gordon Ross
1608d94f65Gordon Ross	return (cr);
1618d94f65Gordon Ross}