12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * CDDL HEADER START
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * The contents of this file are subject to the terms of the
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Common Development and Distribution License (the "License").
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * You may not use this file except in compliance with the License.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * or http://www.opensolaris.org/os/licensing.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * See the License for the specific language governing permissions
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * and limitations under the License.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * If applicable, add the following below this CDDL HEADER, with the
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * CDDL HEADER END
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Authentication helpers for building credentials
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <sys/types.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <sys/sid.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <sys/priv_names.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <sys/socket.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <sys/un.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <netinet/in.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <smbsrv/smb_idmap.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <smbsrv/smb_kproto.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <smbsrv/smb_token.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic void smb_cred_set_sid(smb_id_t *id, ksid_t *ksid);
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic ksidlist_t *smb_cred_set_sidlist(smb_ids_t *token_grps);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Allocate a Solaris cred and initialize it based on the access token.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * If the user can be mapped to a non-ephemeral ID, the cred gid is set
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * to the Solaris user's primary group.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * If the mapped UID is ephemeral, or the primary group could not be
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * obtained, the cred gid is set to whatever Solaris group is mapped
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * to the token's primary group.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rosscred_t *
12b65585e720714b31036daaa2b30eb76014048eGordon Rosssmb_cred_create(smb_token_t *token)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ksid_t ksid;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ksidlist_t *ksidlist = NULL;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_posix_grps_t *posix_grps;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross cred_t *cr;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gid_t gid;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ASSERT(token);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ASSERT(token->tkn_posix_grps);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross posix_grps = token->tkn_posix_grps;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross cr = crget();
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ASSERT(cr != NULL);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (!IDMAP_ID_IS_EPHEMERAL(token->tkn_user.i_id) &&
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (posix_grps->pg_ngrps != 0)) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gid = posix_grps->pg_grps[0];
12b65585e720714b31036daaa2b30eb76014048eGordon Ross } else {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gid = token->tkn_primary_grp.i_id;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (crsetugid(cr, token->tkn_user.i_id, gid) != 0) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross crfree(cr);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NULL);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (crsetgroups(cr, posix_grps->pg_ngrps, posix_grps->pg_grps) != 0) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross crfree(cr);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NULL);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_cred_set_sid(&token->tkn_user, &ksid);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross crsetsid(cr, &ksid, KSID_USER);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_cred_set_sid(&token->tkn_primary_grp, &ksid);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross crsetsid(cr, &ksid, KSID_GROUP);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_cred_set_sid(&token->tkn_owner, &ksid);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross crsetsid(cr, &ksid, KSID_OWNER);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ksidlist = smb_cred_set_sidlist(&token->tkn_win_grps);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross crsetsidlist(cr, ksidlist);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * In the AD world, "take ownership privilege" is very much
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * like having Unix "root" privileges. It's normally given
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * to members of the "Administrators" group, which normally
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * includes the the local Administrator (like root) and when
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * joined to a domain, "Domain Admins".
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) crsetpriv(cr,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross PRIV_FILE_CHOWN,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross PRIV_FILE_DAC_READ,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross PRIV_FILE_DAC_SEARCH,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross PRIV_FILE_DAC_WRITE,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross PRIV_FILE_OWNER,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross NULL);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (cr);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Initialize the ksid based on the given smb_id_t.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic void
12b65585e720714b31036daaa2b30eb76014048eGordon Rosssmb_cred_set_sid(smb_id_t *id, ksid_t *ksid)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross char sidstr[SMB_SID_STRSZ];
12b65585e720714b31036daaa2b30eb76014048eGordon Ross int rc;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ASSERT(id);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ASSERT(id->i_sid);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ksid->ks_id = id->i_id;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_sid_tostr(id->i_sid, sidstr);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross rc = smb_sid_splitstr(sidstr, &ksid->ks_rid);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ASSERT(rc == 0);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ksid->ks_attr = id->i_attrs;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ksid->ks_domain = ksid_lookupdomain(sidstr);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Allocate and initialize the ksidlist based on the access token group list.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic ksidlist_t *
12b65585e720714b31036daaa2b30eb76014048eGordon Rosssmb_cred_set_sidlist(smb_ids_t *token_grps)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross int i;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ksidlist_t *lp;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross lp = kmem_zalloc(KSIDLIST_MEM(token_grps->i_cnt), KM_SLEEP);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross lp->ksl_ref = 1;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross lp->ksl_nsid = token_grps->i_cnt;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross lp->ksl_neid = 0;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross for (i = 0; i < lp->ksl_nsid; i++) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smb_cred_set_sid(&token_grps->i_ids[i], &lp->ksl_sids[i]);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (lp->ksl_sids[i].ks_id > IDMAP_WK__MAX_GID)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross lp->ksl_neid++;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (lp);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}