1*f48205beScasper /* 2*f48205beScasper * CDDL HEADER START 3*f48205beScasper * 4*f48205beScasper * The contents of this file are subject to the terms of the 5*f48205beScasper * Common Development and Distribution License (the "License"). 6*f48205beScasper * You may not use this file except in compliance with the License. 7*f48205beScasper * 8*f48205beScasper * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*f48205beScasper * or http://www.opensolaris.org/os/licensing. 10*f48205beScasper * See the License for the specific language governing permissions 11*f48205beScasper * and limitations under the License. 12*f48205beScasper * 13*f48205beScasper * When distributing Covered Code, include this CDDL HEADER in each 14*f48205beScasper * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*f48205beScasper * If applicable, add the following below this CDDL HEADER, with the 16*f48205beScasper * fields enclosed by brackets "[]" replaced with your own identifying 17*f48205beScasper * information: Portions Copyright [yyyy] [name of copyright owner] 18*f48205beScasper * 19*f48205beScasper * CDDL HEADER END 20*f48205beScasper */ 21*f48205beScasper 22*f48205beScasper /* 23*f48205beScasper * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*f48205beScasper * Use is subject to license terms. 25*f48205beScasper */ 26*f48205beScasper 27*f48205beScasper #pragma ident "%Z%%M% %I% %E% SMI" 28*f48205beScasper 29*f48205beScasper /* 30*f48205beScasper * Sid manipulation (stubs). 31*f48205beScasper */ 32*f48205beScasper 33*f48205beScasper #include <sys/atomic.h> 34*f48205beScasper #include <sys/avl.h> 35*f48205beScasper #include <sys/cmn_err.h> 36*f48205beScasper #include <sys/kmem.h> 37*f48205beScasper #include <sys/mutex.h> 38*f48205beScasper #include <sys/sid.h> 39*f48205beScasper #include <sys/sysmacros.h> 40*f48205beScasper #include <sys/systm.h> 41*f48205beScasper 42*f48205beScasper static kmutex_t sid_lock; 43*f48205beScasper static avl_tree_t sid_tree; 44*f48205beScasper static boolean_t sid_inited = B_FALSE; 45*f48205beScasper 46*f48205beScasper static ksiddomain_t 47*f48205beScasper *ksid_enterdomain(const char *dom) 48*f48205beScasper { 49*f48205beScasper size_t len = strlen(dom) + 1; 50*f48205beScasper ksiddomain_t *res; 51*f48205beScasper 52*f48205beScasper ASSERT(MUTEX_HELD(&sid_lock)); 53*f48205beScasper res = kmem_alloc(sizeof (ksiddomain_t), KM_SLEEP); 54*f48205beScasper res->kd_len = (uint_t)len; 55*f48205beScasper res->kd_name = kmem_alloc(len, KM_SLEEP); 56*f48205beScasper bcopy(dom, res->kd_name, len); 57*f48205beScasper 58*f48205beScasper res->kd_ref = 1; 59*f48205beScasper 60*f48205beScasper avl_add(&sid_tree, res); 61*f48205beScasper 62*f48205beScasper return (res); 63*f48205beScasper } 64*f48205beScasper 65*f48205beScasper void 66*f48205beScasper ksid_hold(ksid_t *ks) 67*f48205beScasper { 68*f48205beScasper if (ks->ks_domain != NULL) 69*f48205beScasper ksiddomain_hold(ks->ks_domain); 70*f48205beScasper } 71*f48205beScasper 72*f48205beScasper void 73*f48205beScasper ksid_rele(ksid_t *ks) 74*f48205beScasper { 75*f48205beScasper if (ks->ks_domain != NULL) 76*f48205beScasper ksiddomain_rele(ks->ks_domain); 77*f48205beScasper } 78*f48205beScasper 79*f48205beScasper void 80*f48205beScasper ksiddomain_hold(ksiddomain_t *kd) 81*f48205beScasper { 82*f48205beScasper atomic_add_32(&kd->kd_ref, 1); 83*f48205beScasper } 84*f48205beScasper 85*f48205beScasper void 86*f48205beScasper ksiddomain_rele(ksiddomain_t *kd) 87*f48205beScasper { 88*f48205beScasper if (atomic_add_32_nv(&kd->kd_ref, -1) == 0) { 89*f48205beScasper /* 90*f48205beScasper * The kd reference can only be incremented from 0 when 91*f48205beScasper * the sid_lock is held; so we lock and then check need to 92*f48205beScasper * check for 0 again. 93*f48205beScasper */ 94*f48205beScasper mutex_enter(&sid_lock); 95*f48205beScasper if (kd->kd_ref == 0) { 96*f48205beScasper avl_remove(&sid_tree, kd); 97*f48205beScasper kmem_free(kd->kd_name, kd->kd_len); 98*f48205beScasper kmem_free(kd, sizeof (*kd)); 99*f48205beScasper } 100*f48205beScasper mutex_exit(&sid_lock); 101*f48205beScasper } 102*f48205beScasper } 103*f48205beScasper 104*f48205beScasper void 105*f48205beScasper ksidlist_hold(ksidlist_t *ksl) 106*f48205beScasper { 107*f48205beScasper atomic_add_32(&ksl->ksl_ref, 1); 108*f48205beScasper } 109*f48205beScasper 110*f48205beScasper void 111*f48205beScasper ksidlist_rele(ksidlist_t *ksl) 112*f48205beScasper { 113*f48205beScasper if (atomic_add_32_nv(&ksl->ksl_ref, -1) == 0) { 114*f48205beScasper int i; 115*f48205beScasper 116*f48205beScasper for (i = 0; i < ksl->ksl_nsid; i++) 117*f48205beScasper ksid_rele(&ksl->ksl_sids[i]); 118*f48205beScasper 119*f48205beScasper kmem_free(ksl, KSIDLIST_MEM(ksl->ksl_nsid)); 120*f48205beScasper } 121*f48205beScasper } 122*f48205beScasper 123*f48205beScasper static int 124*f48205beScasper ksid_cmp(const void *a, const void *b) 125*f48205beScasper { 126*f48205beScasper const ksiddomain_t *ap = a; 127*f48205beScasper const ksiddomain_t *bp = b; 128*f48205beScasper int res; 129*f48205beScasper 130*f48205beScasper res = strcmp(ap->kd_name, bp->kd_name); 131*f48205beScasper if (res > 0) 132*f48205beScasper return (1); 133*f48205beScasper if (res != 0) 134*f48205beScasper return (-1); 135*f48205beScasper return (0); 136*f48205beScasper } 137*f48205beScasper 138*f48205beScasper /* 139*f48205beScasper * Lookup the named domain in the AVL tree. 140*f48205beScasper * If no entry is found, add the domain to the AVL tree. 141*f48205beScasper * The domain is returned held and needs to be released 142*f48205beScasper * when done. 143*f48205beScasper */ 144*f48205beScasper ksiddomain_t 145*f48205beScasper *ksid_lookupdomain(const char *dom) 146*f48205beScasper { 147*f48205beScasper ksiddomain_t *res; 148*f48205beScasper ksiddomain_t tmpl; 149*f48205beScasper 150*f48205beScasper mutex_enter(&sid_lock); 151*f48205beScasper 152*f48205beScasper if (!sid_inited) { 153*f48205beScasper avl_create(&sid_tree, ksid_cmp, sizeof (ksiddomain_t), 154*f48205beScasper offsetof(ksiddomain_t, kd_link)); 155*f48205beScasper 156*f48205beScasper res = ksid_enterdomain(dom); 157*f48205beScasper sid_inited = B_TRUE; 158*f48205beScasper mutex_exit(&sid_lock); 159*f48205beScasper return (res); 160*f48205beScasper } 161*f48205beScasper 162*f48205beScasper tmpl.kd_name = (char *)dom; 163*f48205beScasper 164*f48205beScasper res = avl_find(&sid_tree, &tmpl, NULL); 165*f48205beScasper if (res == NULL) { 166*f48205beScasper res = ksid_enterdomain(dom); 167*f48205beScasper } else { 168*f48205beScasper ksiddomain_hold(res); 169*f48205beScasper } 170*f48205beScasper 171*f48205beScasper mutex_exit(&sid_lock); 172*f48205beScasper return (res); 173*f48205beScasper } 174*f48205beScasper 175*f48205beScasper const char * 176*f48205beScasper ksid_getdomain(ksid_t *ks) 177*f48205beScasper { 178*f48205beScasper return (ks->ks_domain->kd_name); 179*f48205beScasper } 180*f48205beScasper 181*f48205beScasper uint_t 182*f48205beScasper ksid_getrid(ksid_t *ks) 183*f48205beScasper { 184*f48205beScasper return (ks->ks_rid); 185*f48205beScasper } 186*f48205beScasper 187*f48205beScasper int 188*f48205beScasper ksid_lookup(uid_t id, ksid_t *res) 189*f48205beScasper { 190*f48205beScasper uid_t tmp; 191*f48205beScasper 192*f48205beScasper if (idmap_call_byid(id, res) == -1) 193*f48205beScasper return (-1); 194*f48205beScasper 195*f48205beScasper tmp = idmap_call_bysid(res); 196*f48205beScasper if (tmp != id) 197*f48205beScasper cmn_err(CE_WARN, "The idmapper has gone bonkers"); 198*f48205beScasper res->ks_id = id; 199*f48205beScasper 200*f48205beScasper return (0); 201*f48205beScasper } 202*f48205beScasper 203*f48205beScasper credsid_t * 204*f48205beScasper kcrsid_alloc(void) 205*f48205beScasper { 206*f48205beScasper credsid_t *kcr = kmem_zalloc(sizeof (*kcr), KM_SLEEP); 207*f48205beScasper kcr->kr_ref = 1; 208*f48205beScasper return (kcr); 209*f48205beScasper } 210*f48205beScasper 211*f48205beScasper /* 212*f48205beScasper * Returns a credsid_t with a refcount of 1. 213*f48205beScasper */ 214*f48205beScasper static credsid_t * 215*f48205beScasper kcrsid_dup(credsid_t *org) 216*f48205beScasper { 217*f48205beScasper credsid_t *new; 218*f48205beScasper ksid_index_t ki; 219*f48205beScasper 220*f48205beScasper if (org == NULL) 221*f48205beScasper return (kcrsid_alloc()); 222*f48205beScasper if (org->kr_ref == 1) 223*f48205beScasper return (org); 224*f48205beScasper new = kcrsid_alloc(); 225*f48205beScasper 226*f48205beScasper /* Copy, then update reference counts */ 227*f48205beScasper *new = *org; 228*f48205beScasper new->kr_ref = 1; 229*f48205beScasper for (ki = 0; ki < KSID_COUNT; ki++) 230*f48205beScasper ksid_hold(&new->kr_sidx[ki]); 231*f48205beScasper 232*f48205beScasper if (new->kr_sidlist != NULL) 233*f48205beScasper ksidlist_hold(new->kr_sidlist); 234*f48205beScasper 235*f48205beScasper kcrsid_rele(org); 236*f48205beScasper return (new); 237*f48205beScasper } 238*f48205beScasper 239*f48205beScasper void 240*f48205beScasper kcrsid_hold(credsid_t *kcr) 241*f48205beScasper { 242*f48205beScasper atomic_add_32(&kcr->kr_ref, 1); 243*f48205beScasper } 244*f48205beScasper 245*f48205beScasper void 246*f48205beScasper kcrsid_rele(credsid_t *kcr) 247*f48205beScasper { 248*f48205beScasper if (atomic_add_32_nv(&kcr->kr_ref, -1) == 0) { 249*f48205beScasper ksid_index_t i; 250*f48205beScasper 251*f48205beScasper for (i = 0; i < KSID_COUNT; i++) 252*f48205beScasper ksid_rele(&kcr->kr_sidx[i]); 253*f48205beScasper 254*f48205beScasper if (kcr->kr_sidlist != NULL) 255*f48205beScasper ksidlist_rele(kcr->kr_sidlist); 256*f48205beScasper 257*f48205beScasper kmem_free(kcr, sizeof (*kcr)); 258*f48205beScasper } 259*f48205beScasper } 260*f48205beScasper 261*f48205beScasper /* 262*f48205beScasper * Copy the SID credential into a previously allocated piece of memory. 263*f48205beScasper */ 264*f48205beScasper void 265*f48205beScasper kcrsidcopy_to(const credsid_t *okcr, credsid_t *nkcr) 266*f48205beScasper { 267*f48205beScasper int i; 268*f48205beScasper 269*f48205beScasper ASSERT(nkcr->kr_ref == 1); 270*f48205beScasper 271*f48205beScasper if (okcr == NULL) 272*f48205beScasper return; 273*f48205beScasper *nkcr = *okcr; 274*f48205beScasper for (i = 0; i < KSID_COUNT; i++) 275*f48205beScasper ksid_hold(&nkcr->kr_sidx[i]); 276*f48205beScasper if (nkcr->kr_sidlist != NULL) 277*f48205beScasper ksidlist_hold(nkcr->kr_sidlist); 278*f48205beScasper nkcr->kr_ref = 1; 279*f48205beScasper } 280*f48205beScasper 281*f48205beScasper static int 282*f48205beScasper kcrsid_sidcount(const credsid_t *kcr) 283*f48205beScasper { 284*f48205beScasper int cnt = 0; 285*f48205beScasper int i; 286*f48205beScasper 287*f48205beScasper if (kcr == NULL) 288*f48205beScasper return (0); 289*f48205beScasper 290*f48205beScasper for (i = 0; i < KSID_COUNT; i++) 291*f48205beScasper if (kcr->kr_sidx[i].ks_domain != NULL) 292*f48205beScasper cnt++; 293*f48205beScasper 294*f48205beScasper if (kcr->kr_sidlist != NULL) 295*f48205beScasper cnt += kcr->kr_sidlist->ksl_nsid; 296*f48205beScasper return (cnt); 297*f48205beScasper } 298*f48205beScasper 299*f48205beScasper /* 300*f48205beScasper * Argument needs to be a ksid_t with a properly held ks_domain reference. 301*f48205beScasper */ 302*f48205beScasper credsid_t * 303*f48205beScasper kcrsid_setsid(credsid_t *okcr, ksid_t *ksp, ksid_index_t i) 304*f48205beScasper { 305*f48205beScasper int ocnt = kcrsid_sidcount(okcr); 306*f48205beScasper credsid_t *nkcr; 307*f48205beScasper 308*f48205beScasper /* 309*f48205beScasper * Unset the particular ksid; if there are no other SIDs or if this 310*f48205beScasper * is the last SID, remove the auxilary data structure. 311*f48205beScasper */ 312*f48205beScasper if (ksp == NULL) { 313*f48205beScasper if (ocnt == 0 || 314*f48205beScasper (ocnt == 1 && okcr->kr_sidx[i].ks_domain != NULL)) { 315*f48205beScasper if (okcr != NULL) 316*f48205beScasper kcrsid_rele(okcr); 317*f48205beScasper return (NULL); 318*f48205beScasper } 319*f48205beScasper } 320*f48205beScasper nkcr = kcrsid_dup(okcr); 321*f48205beScasper ksid_rele(&nkcr->kr_sidx[i]); 322*f48205beScasper if (ksp == NULL) 323*f48205beScasper bzero(&nkcr->kr_sidx[i], sizeof (ksid_t)); 324*f48205beScasper else 325*f48205beScasper nkcr->kr_sidx[i] = *ksp; 326*f48205beScasper 327*f48205beScasper return (nkcr); 328*f48205beScasper } 329*f48205beScasper 330*f48205beScasper /* 331*f48205beScasper * Argument needs to be a ksidlist_t with properly held ks_domain references 332*f48205beScasper * and a reference count taking the new reference into account. 333*f48205beScasper */ 334*f48205beScasper credsid_t * 335*f48205beScasper kcrsid_setsidlist(credsid_t *okcr, ksidlist_t *ksl) 336*f48205beScasper { 337*f48205beScasper int ocnt = kcrsid_sidcount(okcr); 338*f48205beScasper credsid_t *nkcr; 339*f48205beScasper 340*f48205beScasper /* 341*f48205beScasper * Unset the sidlist; if there are no further SIDs, remove the 342*f48205beScasper * auxilary data structure. 343*f48205beScasper */ 344*f48205beScasper if (ksl == NULL) { 345*f48205beScasper if (ocnt == 0 || (okcr->kr_sidlist != NULL && 346*f48205beScasper ocnt == okcr->kr_sidlist->ksl_nsid)) { 347*f48205beScasper if (okcr != NULL) 348*f48205beScasper kcrsid_rele(okcr); 349*f48205beScasper return (NULL); 350*f48205beScasper } 351*f48205beScasper } 352*f48205beScasper nkcr = kcrsid_dup(okcr); 353*f48205beScasper if (nkcr->kr_sidlist != NULL) 354*f48205beScasper ksidlist_rele(nkcr->kr_sidlist); 355*f48205beScasper 356*f48205beScasper nkcr->kr_sidlist = ksl; 357*f48205beScasper return (nkcr); 358*f48205beScasper } 359*f48205beScasper 360*f48205beScasper ksidlist_t * 361*f48205beScasper kcrsid_gidstosids(int ngrp, gid_t *grp) 362*f48205beScasper { 363*f48205beScasper int i; 364*f48205beScasper ksidlist_t *list; 365*f48205beScasper int cnt; 366*f48205beScasper 367*f48205beScasper if (ngrp == 0) 368*f48205beScasper return (NULL); 369*f48205beScasper 370*f48205beScasper cnt = 0; 371*f48205beScasper list = kmem_zalloc(KSIDLIST_MEM(ngrp), KM_SLEEP); 372*f48205beScasper 373*f48205beScasper list->ksl_nsid = ngrp; 374*f48205beScasper list->ksl_ref = 1; 375*f48205beScasper 376*f48205beScasper for (i = 0; i < ngrp; i++) { 377*f48205beScasper if (grp[i] > MAXUID) { 378*f48205beScasper list->ksl_neid++; 379*f48205beScasper if (ksid_lookup(grp[i], &list->ksl_sids[i]) != 0) { 380*f48205beScasper while (--i >= 0) 381*f48205beScasper ksid_rele(&list->ksl_sids[i]); 382*f48205beScasper cnt = 0; 383*f48205beScasper break; 384*f48205beScasper } 385*f48205beScasper cnt++; 386*f48205beScasper } else { 387*f48205beScasper list->ksl_sids[i].ks_id = grp[i]; 388*f48205beScasper } 389*f48205beScasper } 390*f48205beScasper if (cnt == 0) { 391*f48205beScasper kmem_free(list, KSIDLIST_MEM(ngrp)); 392*f48205beScasper return (NULL); 393*f48205beScasper } 394*f48205beScasper return (list); 395*f48205beScasper } 396