1*45916cd2Sjpk /* 2*45916cd2Sjpk * CDDL HEADER START 3*45916cd2Sjpk * 4*45916cd2Sjpk * The contents of this file are subject to the terms of the 5*45916cd2Sjpk * Common Development and Distribution License (the "License"). 6*45916cd2Sjpk * You may not use this file except in compliance with the License. 7*45916cd2Sjpk * 8*45916cd2Sjpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*45916cd2Sjpk * or http://www.opensolaris.org/os/licensing. 10*45916cd2Sjpk * See the License for the specific language governing permissions 11*45916cd2Sjpk * and limitations under the License. 12*45916cd2Sjpk * 13*45916cd2Sjpk * When distributing Covered Code, include this CDDL HEADER in each 14*45916cd2Sjpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*45916cd2Sjpk * If applicable, add the following below this CDDL HEADER, with the 16*45916cd2Sjpk * fields enclosed by brackets "[]" replaced with your own identifying 17*45916cd2Sjpk * information: Portions Copyright [yyyy] [name of copyright owner] 18*45916cd2Sjpk * 19*45916cd2Sjpk * CDDL HEADER END 20*45916cd2Sjpk */ 21*45916cd2Sjpk /* 22*45916cd2Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*45916cd2Sjpk * Use is subject to license terms. 24*45916cd2Sjpk */ 25*45916cd2Sjpk 26*45916cd2Sjpk #pragma ident "%Z%%M% %I% %E% SMI" 27*45916cd2Sjpk 28*45916cd2Sjpk 29*45916cd2Sjpk /* 30*45916cd2Sjpk * Miscellaneous user interfaces to trusted label functions. 31*45916cd2Sjpk * 32*45916cd2Sjpk */ 33*45916cd2Sjpk 34*45916cd2Sjpk 35*45916cd2Sjpk #include <ctype.h> 36*45916cd2Sjpk #include <stdlib.h> 37*45916cd2Sjpk #include <strings.h> 38*45916cd2Sjpk 39*45916cd2Sjpk #include <sys/mman.h> 40*45916cd2Sjpk 41*45916cd2Sjpk #include <tsol/label.h> 42*45916cd2Sjpk 43*45916cd2Sjpk #include "labeld.h" 44*45916cd2Sjpk #include "clnt.h" 45*45916cd2Sjpk #include <sys/tsol/label_macro.h> 46*45916cd2Sjpk #include <secdb.h> 47*45916cd2Sjpk #include <user_attr.h> 48*45916cd2Sjpk 49*45916cd2Sjpk static bslabel_t slow, shigh; /* static Admin Low and High SLs */ 50*45916cd2Sjpk static bclear_t clow, chigh; /* static Admin Low and High CLRs */ 51*45916cd2Sjpk 52*45916cd2Sjpk static char color[MAXCOLOR]; 53*45916cd2Sjpk 54*45916cd2Sjpk 55*45916cd2Sjpk #define incall callp->param.acall.cargs.inset_arg 56*45916cd2Sjpk #define inret callp->param.aret.rvals.inset_ret 57*45916cd2Sjpk /* 58*45916cd2Sjpk * blinset - Check in a label set. 59*45916cd2Sjpk * 60*45916cd2Sjpk * Entry label = Sensitivity Label to check. 61*45916cd2Sjpk * id = Label set identifier of set to check. 62*45916cd2Sjpk * 63*45916cd2Sjpk * Exit None. 64*45916cd2Sjpk * 65*45916cd2Sjpk * Returns -1, If label set unavailable, or server failure. 66*45916cd2Sjpk * 0, If label not in label set. 67*45916cd2Sjpk * 1, If label is in the label set. 68*45916cd2Sjpk * 69*45916cd2Sjpk * Calls __call_labeld(BLINSET), BLTYPE, BSLLOW, BSLHIGH. 70*45916cd2Sjpk * 71*45916cd2Sjpk * Uses slow, shigh. 72*45916cd2Sjpk */ 73*45916cd2Sjpk 74*45916cd2Sjpk int 75*45916cd2Sjpk blinset(const bslabel_t *label, const set_id *id) 76*45916cd2Sjpk { 77*45916cd2Sjpk if (id->type == SYSTEM_ACCREDITATION_RANGE) { 78*45916cd2Sjpk if (!BLTYPE(&slow, SUN_SL_ID)) { 79*45916cd2Sjpk /* initialize static labels. */ 80*45916cd2Sjpk 81*45916cd2Sjpk BSLLOW(&slow); 82*45916cd2Sjpk BSLHIGH(&shigh); 83*45916cd2Sjpk } 84*45916cd2Sjpk 85*45916cd2Sjpk if (BLTYPE(label, SUN_SL_ID) && 86*45916cd2Sjpk (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh))) 87*45916cd2Sjpk 88*45916cd2Sjpk return (1); 89*45916cd2Sjpk } 90*45916cd2Sjpk if (id->type == USER_ACCREDITATION_RANGE || 91*45916cd2Sjpk id->type == SYSTEM_ACCREDITATION_RANGE) { 92*45916cd2Sjpk labeld_data_t call; 93*45916cd2Sjpk labeld_data_t *callp = &call; 94*45916cd2Sjpk size_t bufsize = sizeof (labeld_data_t); 95*45916cd2Sjpk size_t datasize = CALL_SIZE(inset_call_t, 0); 96*45916cd2Sjpk 97*45916cd2Sjpk call.callop = BLINSET; 98*45916cd2Sjpk incall.label = *label; 99*45916cd2Sjpk incall.type = id->type; 100*45916cd2Sjpk 101*45916cd2Sjpk if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) { 102*45916cd2Sjpk /* process error */ 103*45916cd2Sjpk 104*45916cd2Sjpk return (-1); 105*45916cd2Sjpk } 106*45916cd2Sjpk return (inret.inset); 107*45916cd2Sjpk } else { 108*45916cd2Sjpk /* 109*45916cd2Sjpk * Only System and User Accreditation Ranges presently 110*45916cd2Sjpk * implemented. 111*45916cd2Sjpk */ 112*45916cd2Sjpk return (-1); 113*45916cd2Sjpk } 114*45916cd2Sjpk } 115*45916cd2Sjpk #undef incall 116*45916cd2Sjpk #undef inret 117*45916cd2Sjpk 118*45916cd2Sjpk #define slvcall callp->param.acall.cargs.slvalid_arg 119*45916cd2Sjpk #define slvret callp->param.aret.rvals.slvalid_ret 120*45916cd2Sjpk /* 121*45916cd2Sjpk * bslvalid - Check Sensitivity Label for validity. 122*45916cd2Sjpk * 123*45916cd2Sjpk * Entry label = Sensitivity Label to check. 124*45916cd2Sjpk * 125*45916cd2Sjpk * Exit None. 126*45916cd2Sjpk * 127*45916cd2Sjpk * Returns -1, If unable to access label encodings file, or server failure. 128*45916cd2Sjpk * 0, If label not valid. 129*45916cd2Sjpk * 1, If label is valid. 130*45916cd2Sjpk * 131*45916cd2Sjpk * Calls __call_labeld(BSLVALID), BLTYPE, BSLLOW, BSLHIGH. 132*45916cd2Sjpk * 133*45916cd2Sjpk * Uses slow, shigh. 134*45916cd2Sjpk * 135*45916cd2Sjpk */ 136*45916cd2Sjpk 137*45916cd2Sjpk int 138*45916cd2Sjpk bslvalid(const bslabel_t *label) 139*45916cd2Sjpk { 140*45916cd2Sjpk labeld_data_t call; 141*45916cd2Sjpk labeld_data_t *callp = &call; 142*45916cd2Sjpk size_t bufsize = sizeof (labeld_data_t); 143*45916cd2Sjpk size_t datasize = CALL_SIZE(slvalid_call_t, 0); 144*45916cd2Sjpk 145*45916cd2Sjpk if (!BLTYPE(&slow, SUN_SL_ID)) { 146*45916cd2Sjpk /* initialize static labels. */ 147*45916cd2Sjpk 148*45916cd2Sjpk BSLLOW(&slow); 149*45916cd2Sjpk BSLHIGH(&shigh); 150*45916cd2Sjpk } 151*45916cd2Sjpk 152*45916cd2Sjpk if (BLTYPE(label, SUN_SL_ID) && 153*45916cd2Sjpk (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh))) { 154*45916cd2Sjpk 155*45916cd2Sjpk return (1); 156*45916cd2Sjpk } 157*45916cd2Sjpk 158*45916cd2Sjpk call.callop = BSLVALID; 159*45916cd2Sjpk slvcall.label = *label; 160*45916cd2Sjpk 161*45916cd2Sjpk if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) { 162*45916cd2Sjpk /* process error */ 163*45916cd2Sjpk 164*45916cd2Sjpk return (-1); 165*45916cd2Sjpk } 166*45916cd2Sjpk return (slvret.valid); 167*45916cd2Sjpk } 168*45916cd2Sjpk #undef slvcall 169*45916cd2Sjpk #undef slvret 170*45916cd2Sjpk 171*45916cd2Sjpk #define clrvcall callp->param.acall.cargs.clrvalid_arg 172*45916cd2Sjpk #define clrvret callp->param.aret.rvals.clrvalid_ret 173*45916cd2Sjpk /* 174*45916cd2Sjpk * bclearvalid - Check Clearance for validity. 175*45916cd2Sjpk * 176*45916cd2Sjpk * Entry clearance = Clearance to check. 177*45916cd2Sjpk * 178*45916cd2Sjpk * Exit None. 179*45916cd2Sjpk * 180*45916cd2Sjpk * Returns -1, If unable to access label encodings file, or server failure. 181*45916cd2Sjpk * 0, If label not valid. 182*45916cd2Sjpk * 1, If label is valid. 183*45916cd2Sjpk * 184*45916cd2Sjpk * Calls __call_labeld(BCLEARVALID), BLTYPE, BCLEARLOW, BCLEARHIGH. 185*45916cd2Sjpk * 186*45916cd2Sjpk * Uses clow, chigh. 187*45916cd2Sjpk * 188*45916cd2Sjpk */ 189*45916cd2Sjpk 190*45916cd2Sjpk int 191*45916cd2Sjpk bclearvalid(const bclear_t *clearance) 192*45916cd2Sjpk { 193*45916cd2Sjpk labeld_data_t call; 194*45916cd2Sjpk labeld_data_t *callp = &call; 195*45916cd2Sjpk size_t bufsize = sizeof (labeld_data_t); 196*45916cd2Sjpk size_t datasize = CALL_SIZE(clrvalid_call_t, 0); 197*45916cd2Sjpk 198*45916cd2Sjpk if (!BLTYPE(&clow, SUN_CLR_ID)) { 199*45916cd2Sjpk /* initialize static labels. */ 200*45916cd2Sjpk 201*45916cd2Sjpk BCLEARLOW(&clow); 202*45916cd2Sjpk BCLEARHIGH(&chigh); 203*45916cd2Sjpk } 204*45916cd2Sjpk 205*45916cd2Sjpk if (BLTYPE(clearance, SUN_CLR_ID) && 206*45916cd2Sjpk (BLEQUAL(clearance, &clow) || BLEQUAL(clearance, &chigh))) { 207*45916cd2Sjpk 208*45916cd2Sjpk return (1); 209*45916cd2Sjpk } 210*45916cd2Sjpk 211*45916cd2Sjpk call.callop = BCLEARVALID; 212*45916cd2Sjpk clrvcall.clear = *clearance; 213*45916cd2Sjpk 214*45916cd2Sjpk if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) { 215*45916cd2Sjpk /* process error */ 216*45916cd2Sjpk 217*45916cd2Sjpk return (-1); 218*45916cd2Sjpk } 219*45916cd2Sjpk return (clrvret.valid); 220*45916cd2Sjpk } 221*45916cd2Sjpk #undef clrvcall 222*45916cd2Sjpk #undef clrvret 223*45916cd2Sjpk 224*45916cd2Sjpk #define inforet callp->param.aret.rvals.info_ret 225*45916cd2Sjpk /* 226*45916cd2Sjpk * labelinfo - Get information about the label encodings file. 227*45916cd2Sjpk * 228*45916cd2Sjpk * Entry info = Address of label_info structure to update. 229*45916cd2Sjpk * 230*45916cd2Sjpk * Exit info = Updated. 231*45916cd2Sjpk * 232*45916cd2Sjpk * Returns -1, If unable to access label encodings file, or server failure. 233*45916cd2Sjpk * 1, If successful. 234*45916cd2Sjpk * 235*45916cd2Sjpk * Calls __call_labeld(LABELINFO). 236*45916cd2Sjpk */ 237*45916cd2Sjpk 238*45916cd2Sjpk int 239*45916cd2Sjpk labelinfo(struct label_info *info) 240*45916cd2Sjpk { 241*45916cd2Sjpk labeld_data_t call; 242*45916cd2Sjpk labeld_data_t *callp = &call; 243*45916cd2Sjpk size_t bufsize = sizeof (labeld_data_t); 244*45916cd2Sjpk size_t datasize = CALL_SIZE(info_call_t, 0); 245*45916cd2Sjpk int rval; 246*45916cd2Sjpk 247*45916cd2Sjpk call.callop = LABELINFO; 248*45916cd2Sjpk 249*45916cd2Sjpk if ((rval = __call_labeld(&callp, &bufsize, &datasize)) != SUCCESS) { 250*45916cd2Sjpk /* process error */ 251*45916cd2Sjpk 252*45916cd2Sjpk return (-1); 253*45916cd2Sjpk } 254*45916cd2Sjpk *info = inforet.info; 255*45916cd2Sjpk return (rval); 256*45916cd2Sjpk } 257*45916cd2Sjpk #undef inforet 258*45916cd2Sjpk 259*45916cd2Sjpk #define lvret callp->param.aret.rvals.vers_ret 260*45916cd2Sjpk /* 261*45916cd2Sjpk * labelvers - Get version string of the label encodings file. 262*45916cd2Sjpk * 263*45916cd2Sjpk * Entry version = Address of string pointer to return. 264*45916cd2Sjpk * len = Length of string if pre-allocated. 265*45916cd2Sjpk * 266*45916cd2Sjpk * Exit version = Updated. 267*45916cd2Sjpk * 268*45916cd2Sjpk * Returns -1, If unable to access label encodings file, or server failure. 269*45916cd2Sjpk * 0, If unable to allocate version string, 270*45916cd2Sjpk * or pre-allocated version string to short 271*45916cd2Sjpk * (and **version = '\0'). 272*45916cd2Sjpk * length (including null) of version string, If successful. 273*45916cd2Sjpk * 274*45916cd2Sjpk * Calls __call_labeld(LABELVERS) 275*45916cd2Sjpk * malloc, strlen. 276*45916cd2Sjpk */ 277*45916cd2Sjpk 278*45916cd2Sjpk ssize_t 279*45916cd2Sjpk labelvers(char **version, size_t len) 280*45916cd2Sjpk { 281*45916cd2Sjpk labeld_data_t call; 282*45916cd2Sjpk labeld_data_t *callp = &call; 283*45916cd2Sjpk size_t bufsize = sizeof (labeld_data_t); 284*45916cd2Sjpk size_t datasize = CALL_SIZE(vers_call_t, 0); 285*45916cd2Sjpk size_t ver_len; 286*45916cd2Sjpk 287*45916cd2Sjpk call.callop = LABELVERS; 288*45916cd2Sjpk 289*45916cd2Sjpk if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) { 290*45916cd2Sjpk 291*45916cd2Sjpk if (callp != &call) 292*45916cd2Sjpk /* release return buffer */ 293*45916cd2Sjpk (void) munmap((void *)callp, bufsize); 294*45916cd2Sjpk return (-1); 295*45916cd2Sjpk } 296*45916cd2Sjpk 297*45916cd2Sjpk /* unpack length */ 298*45916cd2Sjpk 299*45916cd2Sjpk ver_len = strlen(lvret.vers) + 1; 300*45916cd2Sjpk if (*version == NULL) { 301*45916cd2Sjpk if ((*version = malloc(ver_len)) == NULL) { 302*45916cd2Sjpk if (callp != &call) 303*45916cd2Sjpk /* release return buffer */ 304*45916cd2Sjpk (void) munmap((void *)callp, bufsize); 305*45916cd2Sjpk return (0); 306*45916cd2Sjpk } 307*45916cd2Sjpk } else if (ver_len > len) { 308*45916cd2Sjpk **version = '\0'; 309*45916cd2Sjpk if (callp != &call) 310*45916cd2Sjpk /* release return buffer */ 311*45916cd2Sjpk (void) munmap((void *)callp, bufsize); 312*45916cd2Sjpk return (0); 313*45916cd2Sjpk } 314*45916cd2Sjpk (void) strcpy(*version, lvret.vers); 315*45916cd2Sjpk 316*45916cd2Sjpk if (callp != &call) 317*45916cd2Sjpk /* release return buffer */ 318*45916cd2Sjpk (void) munmap((void *)callp, bufsize); 319*45916cd2Sjpk return (ver_len); 320*45916cd2Sjpk } /* labelvers */ 321*45916cd2Sjpk #undef lvret 322*45916cd2Sjpk 323*45916cd2Sjpk #define ccall callp->param.acall.cargs.color_arg 324*45916cd2Sjpk #define cret callp->param.aret.rvals.color_ret 325*45916cd2Sjpk /* 326*45916cd2Sjpk * bltocolor - get ASCII color name of label. 327*45916cd2Sjpk * 328*45916cd2Sjpk * Entry label = Sensitivity Level of color to get. 329*45916cd2Sjpk * size = Size of the color_name array. 330*45916cd2Sjpk * color_name = Storage for ASCII color name string to be returned. 331*45916cd2Sjpk * 332*45916cd2Sjpk * Exit None. 333*45916cd2Sjpk * 334*45916cd2Sjpk * Returns NULL, If error (label encodings file not accessible, 335*45916cd2Sjpk * invalid label, no color for this label). 336*45916cd2Sjpk * Address of color_name parameter containing ASCII color name 337*45916cd2Sjpk * defined for the label. 338*45916cd2Sjpk * 339*45916cd2Sjpk * Calls __call_labeld(BLTOCOLOR), strlen. 340*45916cd2Sjpk */ 341*45916cd2Sjpk 342*45916cd2Sjpk char * 343*45916cd2Sjpk bltocolor_r(const blevel_t *label, size_t size, char *color_name) 344*45916cd2Sjpk { 345*45916cd2Sjpk labeld_data_t call; 346*45916cd2Sjpk labeld_data_t *callp = &call; 347*45916cd2Sjpk size_t bufsize = sizeof (labeld_data_t); 348*45916cd2Sjpk size_t datasize = CALL_SIZE(color_call_t, 0); 349*45916cd2Sjpk char *colorp; 350*45916cd2Sjpk 351*45916cd2Sjpk call.callop = BLTOCOLOR; 352*45916cd2Sjpk ccall.label = *label; 353*45916cd2Sjpk 354*45916cd2Sjpk if ((__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) || 355*45916cd2Sjpk (callp->reterr != 0) || 356*45916cd2Sjpk (strlen(cret.color) >= size)) { 357*45916cd2Sjpk 358*45916cd2Sjpk if (callp != &call) 359*45916cd2Sjpk /* release return buffer */ 360*45916cd2Sjpk (void) munmap((void *)callp, bufsize); 361*45916cd2Sjpk return (NULL); 362*45916cd2Sjpk } 363*45916cd2Sjpk 364*45916cd2Sjpk colorp = strcpy(color_name, cret.color); 365*45916cd2Sjpk 366*45916cd2Sjpk if (callp != &call) 367*45916cd2Sjpk /* release return buffer */ 368*45916cd2Sjpk (void) munmap((void *)callp, bufsize); 369*45916cd2Sjpk return (colorp); 370*45916cd2Sjpk } /* bltocolor_r */ 371*45916cd2Sjpk #undef ccall 372*45916cd2Sjpk #undef cret 373*45916cd2Sjpk 374*45916cd2Sjpk /* 375*45916cd2Sjpk * bltocolor - get ASCII color name of label. 376*45916cd2Sjpk * 377*45916cd2Sjpk * Entry label = Sensitivity Level of color to get. 378*45916cd2Sjpk * 379*45916cd2Sjpk * Exit None. 380*45916cd2Sjpk * 381*45916cd2Sjpk * Returns NULL, If error (label encodings file not accessible, 382*45916cd2Sjpk * invalid label, no color for this label). 383*45916cd2Sjpk * Address of statically allocated string containing ASCII 384*45916cd2Sjpk * color name defined for the classification contained 385*45916cd2Sjpk * in label. 386*45916cd2Sjpk * 387*45916cd2Sjpk * Uses color. 388*45916cd2Sjpk * 389*45916cd2Sjpk * Calls bltocolor_r. 390*45916cd2Sjpk */ 391*45916cd2Sjpk 392*45916cd2Sjpk char * 393*45916cd2Sjpk bltocolor(const blevel_t *label) 394*45916cd2Sjpk { 395*45916cd2Sjpk return (bltocolor_r(label, sizeof (color), color)); 396*45916cd2Sjpk } /* bltocolor */ 397*45916cd2Sjpk 398*45916cd2Sjpk blevel_t * 399*45916cd2Sjpk blabel_alloc(void) 400*45916cd2Sjpk { 401*45916cd2Sjpk return (m_label_alloc(MAC_LABEL)); 402*45916cd2Sjpk } 403*45916cd2Sjpk 404*45916cd2Sjpk void 405*45916cd2Sjpk blabel_free(blevel_t *label_p) 406*45916cd2Sjpk { 407*45916cd2Sjpk free(label_p); 408*45916cd2Sjpk } 409*45916cd2Sjpk 410*45916cd2Sjpk size_t 411*45916cd2Sjpk blabel_size(void) 412*45916cd2Sjpk { 413*45916cd2Sjpk return (sizeof (blevel_t)); 414*45916cd2Sjpk } 415*45916cd2Sjpk 416*45916cd2Sjpk /* 417*45916cd2Sjpk * getuserrange - get label range for user 418*45916cd2Sjpk * 419*45916cd2Sjpk * Entry username of user 420*45916cd2Sjpk * 421*45916cd2Sjpk * Exit None. 422*45916cd2Sjpk * 423*45916cd2Sjpk * Returns NULL, If memory allocation failure or userdefs failure. 424*45916cd2Sjpk * otherwise returns the allocates m_range_t with the 425*45916cd2Sjpk * user's min and max labels set. 426*45916cd2Sjpk */ 427*45916cd2Sjpk 428*45916cd2Sjpk m_range_t * 429*45916cd2Sjpk getuserrange(const char *username) 430*45916cd2Sjpk { 431*45916cd2Sjpk char *kv_str = NULL; 432*45916cd2Sjpk userattr_t *userp = NULL; 433*45916cd2Sjpk m_range_t *range; 434*45916cd2Sjpk int err; 435*45916cd2Sjpk 436*45916cd2Sjpk /* 437*45916cd2Sjpk * Get some memory 438*45916cd2Sjpk */ 439*45916cd2Sjpk 440*45916cd2Sjpk if ((range = malloc(sizeof (m_range_t))) == NULL) { 441*45916cd2Sjpk return (NULL); 442*45916cd2Sjpk } 443*45916cd2Sjpk if ((range->lower_bound = m_label_alloc(MAC_LABEL)) == NULL) { 444*45916cd2Sjpk free(range); 445*45916cd2Sjpk return (NULL); 446*45916cd2Sjpk } 447*45916cd2Sjpk if ((range->upper_bound = m_label_alloc(USER_CLEAR)) == NULL) { 448*45916cd2Sjpk m_label_free(range->lower_bound); 449*45916cd2Sjpk free(range); 450*45916cd2Sjpk return (NULL); 451*45916cd2Sjpk } 452*45916cd2Sjpk /* 453*45916cd2Sjpk * Since user_attr entries are optional, start with 454*45916cd2Sjpk * the system default values 455*45916cd2Sjpk */ 456*45916cd2Sjpk if ((userdefs(range->lower_bound, range->upper_bound)) == -1) { 457*45916cd2Sjpk m_label_free(range->lower_bound); 458*45916cd2Sjpk m_label_free(range->upper_bound); 459*45916cd2Sjpk free(range); 460*45916cd2Sjpk return (NULL); 461*45916cd2Sjpk } 462*45916cd2Sjpk /* 463*45916cd2Sjpk * If the user has an explicit min_label or clearance, 464*45916cd2Sjpk * then use it instead. 465*45916cd2Sjpk */ 466*45916cd2Sjpk if ((userp = getusernam(username)) == NULL) { 467*45916cd2Sjpk return (range); 468*45916cd2Sjpk } 469*45916cd2Sjpk if ((kv_str = kva_match(userp->attr, USERATTR_MINLABEL)) != NULL) 470*45916cd2Sjpk (void) stobsl(kv_str, range->lower_bound, NO_CORRECTION, &err); 471*45916cd2Sjpk if ((kv_str = kva_match(userp->attr, USERATTR_CLEARANCE)) != NULL) 472*45916cd2Sjpk (void) stobclear(kv_str, range->upper_bound, NO_CORRECTION, 473*45916cd2Sjpk &err); 474*45916cd2Sjpk free_userattr(userp); 475*45916cd2Sjpk return (range); 476*45916cd2Sjpk } 477