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.
23*5d8538b6SGordon Ross * Copyright 2020 Nexenta by DDN, Inc. All rights reserved.
24*5d8538b6SGordon Ross * Copyright 2023 RackTop Systems, Inc.
2512b65585SGordon Ross */
2612b65585SGordon Ross
2712b65585SGordon Ross /*
2812b65585SGordon Ross * Authentication helpers for building credentials
2912b65585SGordon Ross */
3012b65585SGordon Ross
3112b65585SGordon Ross #include <sys/types.h>
32*5d8538b6SGordon Ross #include <sys/cred.h>
33*5d8538b6SGordon Ross #include <sys/cred_impl.h>
3412b65585SGordon Ross #include <sys/sid.h>
3512b65585SGordon Ross #include <sys/priv_names.h>
3612b65585SGordon Ross #include <sys/socket.h>
3712b65585SGordon Ross #include <sys/un.h>
3812b65585SGordon Ross #include <netinet/in.h>
3912b65585SGordon Ross #include <smbsrv/smb_idmap.h>
4012b65585SGordon Ross #include <smbsrv/smb_kproto.h>
4112b65585SGordon Ross #include <smbsrv/smb_token.h>
4212b65585SGordon Ross
4312b65585SGordon Ross static void smb_cred_set_sid(smb_id_t *id, ksid_t *ksid);
4412b65585SGordon Ross static ksidlist_t *smb_cred_set_sidlist(smb_ids_t *token_grps);
4512b65585SGordon Ross
4612b65585SGordon Ross /*
4712b65585SGordon Ross * Allocate a Solaris cred and initialize it based on the access token.
4812b65585SGordon Ross *
4912b65585SGordon Ross * If the user can be mapped to a non-ephemeral ID, the cred gid is set
5012b65585SGordon Ross * to the Solaris user's primary group.
5112b65585SGordon Ross *
5212b65585SGordon Ross * If the mapped UID is ephemeral, or the primary group could not be
5312b65585SGordon Ross * obtained, the cred gid is set to whatever Solaris group is mapped
5412b65585SGordon Ross * to the token's primary group.
55cc3780e6SGordon Ross *
56cc3780e6SGordon Ross * Also add any privileges that should always be in effect for this user.
57cc3780e6SGordon Ross * Note that an SMB user object also gets a u_privcred which is used
58cc3780e6SGordon Ross * when the client opens an object with "backup/restore intent".
59cc3780e6SGordon Ross * That cred is setup later, in smb_user_setcred().
6012b65585SGordon Ross */
6112b65585SGordon Ross cred_t *
smb_cred_create(smb_token_t * token)6212b65585SGordon Ross smb_cred_create(smb_token_t *token)
6312b65585SGordon Ross {
6412b65585SGordon Ross ksid_t ksid;
6512b65585SGordon Ross ksidlist_t *ksidlist = NULL;
6612b65585SGordon Ross smb_posix_grps_t *posix_grps;
6712b65585SGordon Ross cred_t *cr;
6812b65585SGordon Ross gid_t gid;
6912b65585SGordon Ross
7012b65585SGordon Ross ASSERT(token);
7112b65585SGordon Ross ASSERT(token->tkn_posix_grps);
7212b65585SGordon Ross posix_grps = token->tkn_posix_grps;
7312b65585SGordon Ross
7412b65585SGordon Ross cr = crget();
7512b65585SGordon Ross ASSERT(cr != NULL);
7612b65585SGordon Ross
77*5d8538b6SGordon Ross /*
78*5d8538b6SGordon Ross * Add (preserve) PRIV_SYS_SMB in the permitted set.
79*5d8538b6SGordon Ross * See the privilege check in smbd:pipe_has_priv
80*5d8538b6SGordon Ross */
81*5d8538b6SGordon Ross priv_addset(&CR_PPRIV(cr), PRIV_SYS_SMB);
82*5d8538b6SGordon Ross
8312b65585SGordon Ross if (!IDMAP_ID_IS_EPHEMERAL(token->tkn_user.i_id) &&
8412b65585SGordon Ross (posix_grps->pg_ngrps != 0)) {
8512b65585SGordon Ross gid = posix_grps->pg_grps[0];
8612b65585SGordon Ross } else {
8712b65585SGordon Ross gid = token->tkn_primary_grp.i_id;
8812b65585SGordon Ross }
8912b65585SGordon Ross
9012b65585SGordon Ross if (crsetugid(cr, token->tkn_user.i_id, gid) != 0) {
9112b65585SGordon Ross crfree(cr);
9212b65585SGordon Ross return (NULL);
9312b65585SGordon Ross }
9412b65585SGordon Ross
9512b65585SGordon Ross if (crsetgroups(cr, posix_grps->pg_ngrps, posix_grps->pg_grps) != 0) {
9612b65585SGordon Ross crfree(cr);
9712b65585SGordon Ross return (NULL);
9812b65585SGordon Ross }
9912b65585SGordon Ross
10012b65585SGordon Ross smb_cred_set_sid(&token->tkn_user, &ksid);
10112b65585SGordon Ross crsetsid(cr, &ksid, KSID_USER);
10212b65585SGordon Ross smb_cred_set_sid(&token->tkn_primary_grp, &ksid);
10312b65585SGordon Ross crsetsid(cr, &ksid, KSID_GROUP);
10412b65585SGordon Ross smb_cred_set_sid(&token->tkn_owner, &ksid);
10512b65585SGordon Ross crsetsid(cr, &ksid, KSID_OWNER);
10612b65585SGordon Ross ksidlist = smb_cred_set_sidlist(&token->tkn_win_grps);
10712b65585SGordon Ross crsetsidlist(cr, ksidlist);
10812b65585SGordon Ross
10912b65585SGordon Ross return (cr);
11012b65585SGordon Ross }
11112b65585SGordon Ross
11212b65585SGordon Ross /*
11312b65585SGordon Ross * Initialize the ksid based on the given smb_id_t.
11412b65585SGordon Ross */
11512b65585SGordon Ross static void
smb_cred_set_sid(smb_id_t * id,ksid_t * ksid)11612b65585SGordon Ross smb_cred_set_sid(smb_id_t *id, ksid_t *ksid)
11712b65585SGordon Ross {
11812b65585SGordon Ross char sidstr[SMB_SID_STRSZ];
11912b65585SGordon Ross int rc;
12012b65585SGordon Ross
12112b65585SGordon Ross ASSERT(id);
12212b65585SGordon Ross ASSERT(id->i_sid);
12312b65585SGordon Ross
12412b65585SGordon Ross ksid->ks_id = id->i_id;
12512b65585SGordon Ross smb_sid_tostr(id->i_sid, sidstr);
12612b65585SGordon Ross rc = smb_sid_splitstr(sidstr, &ksid->ks_rid);
12712b65585SGordon Ross ASSERT(rc == 0);
12812b65585SGordon Ross
12912b65585SGordon Ross ksid->ks_attr = id->i_attrs;
13012b65585SGordon Ross ksid->ks_domain = ksid_lookupdomain(sidstr);
13112b65585SGordon Ross }
13212b65585SGordon Ross
13312b65585SGordon Ross /*
13412b65585SGordon Ross * Allocate and initialize the ksidlist based on the access token group list.
13512b65585SGordon Ross */
13612b65585SGordon Ross static ksidlist_t *
smb_cred_set_sidlist(smb_ids_t * token_grps)13712b65585SGordon Ross smb_cred_set_sidlist(smb_ids_t *token_grps)
13812b65585SGordon Ross {
13912b65585SGordon Ross int i;
14012b65585SGordon Ross ksidlist_t *lp;
14112b65585SGordon Ross
14212b65585SGordon Ross lp = kmem_zalloc(KSIDLIST_MEM(token_grps->i_cnt), KM_SLEEP);
14312b65585SGordon Ross lp->ksl_ref = 1;
14412b65585SGordon Ross lp->ksl_nsid = token_grps->i_cnt;
14512b65585SGordon Ross lp->ksl_neid = 0;
14612b65585SGordon Ross
14712b65585SGordon Ross for (i = 0; i < lp->ksl_nsid; i++) {
14812b65585SGordon Ross smb_cred_set_sid(&token_grps->i_ids[i], &lp->ksl_sids[i]);
14912b65585SGordon Ross if (lp->ksl_sids[i].ks_id > IDMAP_WK__MAX_GID)
15012b65585SGordon Ross lp->ksl_neid++;
15112b65585SGordon Ross }
15212b65585SGordon Ross
15312b65585SGordon Ross return (lp);
15412b65585SGordon Ross }
1558d94f651SGordon Ross
1568d94f651SGordon Ross /*
1578d94f651SGordon Ross * Special variant of smb_cred_create() used when we need an
1588d94f651SGordon Ross * SMB kcred (e.g. DH import). The returned cred must be
1598d94f651SGordon Ross * from crget() so it can be passed to smb_user_setcred().
1608d94f651SGordon Ross */
1618d94f651SGordon Ross cred_t *
smb_kcred_create(void)1628d94f651SGordon Ross smb_kcred_create(void)
1638d94f651SGordon Ross {
1648d94f651SGordon Ross cred_t *cr;
1658d94f651SGordon Ross
1668d94f651SGordon Ross cr = crget();
1678d94f651SGordon Ross ASSERT(cr != NULL);
1688d94f651SGordon Ross
1698d94f651SGordon Ross return (cr);
1708d94f651SGordon Ross }
171