1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. 24 */ 25 26 /* 27 * Authentication helpers for building credentials 28 */ 29 30 #include <sys/types.h> 31 #include <sys/sid.h> 32 #include <sys/priv_names.h> 33 #include <sys/socket.h> 34 #include <sys/un.h> 35 #include <netinet/in.h> 36 #include <smbsrv/smb_idmap.h> 37 #include <smbsrv/smb_kproto.h> 38 #include <smbsrv/smb_token.h> 39 40 static void smb_cred_set_sid(smb_id_t *id, ksid_t *ksid); 41 static ksidlist_t *smb_cred_set_sidlist(smb_ids_t *token_grps); 42 43 /* 44 * Allocate a Solaris cred and initialize it based on the access token. 45 * 46 * If the user can be mapped to a non-ephemeral ID, the cred gid is set 47 * to the Solaris user's primary group. 48 * 49 * If the mapped UID is ephemeral, or the primary group could not be 50 * obtained, the cred gid is set to whatever Solaris group is mapped 51 * to the token's primary group. 52 * 53 * Also add any privileges that should always be in effect for this user. 54 * Note that an SMB user object also gets a u_privcred which is used 55 * when the client opens an object with "backup/restore intent". 56 * That cred is setup later, in smb_user_setcred(). 57 */ 58 cred_t * 59 smb_cred_create(smb_token_t *token) 60 { 61 ksid_t ksid; 62 ksidlist_t *ksidlist = NULL; 63 smb_posix_grps_t *posix_grps; 64 cred_t *cr; 65 gid_t gid; 66 67 ASSERT(token); 68 ASSERT(token->tkn_posix_grps); 69 posix_grps = token->tkn_posix_grps; 70 71 cr = crget(); 72 ASSERT(cr != NULL); 73 74 if (!IDMAP_ID_IS_EPHEMERAL(token->tkn_user.i_id) && 75 (posix_grps->pg_ngrps != 0)) { 76 gid = posix_grps->pg_grps[0]; 77 } else { 78 gid = token->tkn_primary_grp.i_id; 79 } 80 81 if (crsetugid(cr, token->tkn_user.i_id, gid) != 0) { 82 crfree(cr); 83 return (NULL); 84 } 85 86 if (crsetgroups(cr, posix_grps->pg_ngrps, posix_grps->pg_grps) != 0) { 87 crfree(cr); 88 return (NULL); 89 } 90 91 smb_cred_set_sid(&token->tkn_user, &ksid); 92 crsetsid(cr, &ksid, KSID_USER); 93 smb_cred_set_sid(&token->tkn_primary_grp, &ksid); 94 crsetsid(cr, &ksid, KSID_GROUP); 95 smb_cred_set_sid(&token->tkn_owner, &ksid); 96 crsetsid(cr, &ksid, KSID_OWNER); 97 ksidlist = smb_cred_set_sidlist(&token->tkn_win_grps); 98 crsetsidlist(cr, ksidlist); 99 100 return (cr); 101 } 102 103 /* 104 * Initialize the ksid based on the given smb_id_t. 105 */ 106 static void 107 smb_cred_set_sid(smb_id_t *id, ksid_t *ksid) 108 { 109 char sidstr[SMB_SID_STRSZ]; 110 int rc; 111 112 ASSERT(id); 113 ASSERT(id->i_sid); 114 115 ksid->ks_id = id->i_id; 116 smb_sid_tostr(id->i_sid, sidstr); 117 rc = smb_sid_splitstr(sidstr, &ksid->ks_rid); 118 ASSERT(rc == 0); 119 120 ksid->ks_attr = id->i_attrs; 121 ksid->ks_domain = ksid_lookupdomain(sidstr); 122 } 123 124 /* 125 * Allocate and initialize the ksidlist based on the access token group list. 126 */ 127 static ksidlist_t * 128 smb_cred_set_sidlist(smb_ids_t *token_grps) 129 { 130 int i; 131 ksidlist_t *lp; 132 133 lp = kmem_zalloc(KSIDLIST_MEM(token_grps->i_cnt), KM_SLEEP); 134 lp->ksl_ref = 1; 135 lp->ksl_nsid = token_grps->i_cnt; 136 lp->ksl_neid = 0; 137 138 for (i = 0; i < lp->ksl_nsid; i++) { 139 smb_cred_set_sid(&token_grps->i_ids[i], &lp->ksl_sids[i]); 140 if (lp->ksl_sids[i].ks_id > IDMAP_WK__MAX_GID) 141 lp->ksl_neid++; 142 } 143 144 return (lp); 145 } 146 147 /* 148 * Special variant of smb_cred_create() used when we need an 149 * SMB kcred (e.g. DH import). The returned cred must be 150 * from crget() so it can be passed to smb_user_setcred(). 151 */ 152 cred_t * 153 smb_kcred_create(void) 154 { 155 cred_t *cr; 156 157 cr = crget(); 158 ASSERT(cr != NULL); 159 160 return (cr); 161 } 162