xref: /titanic_50/usr/src/lib/libtsol/common/misc.c (revision 42096647a1cb1ee493b238f2713f001b8b039514)
145916cd2Sjpk /*
245916cd2Sjpk  * CDDL HEADER START
345916cd2Sjpk  *
445916cd2Sjpk  * The contents of this file are subject to the terms of the
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * You may not use this file except in compliance with the License.
745916cd2Sjpk  *
845916cd2Sjpk  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
945916cd2Sjpk  * or http://www.opensolaris.org/os/licensing.
1045916cd2Sjpk  * See the License for the specific language governing permissions
1145916cd2Sjpk  * and limitations under the License.
1245916cd2Sjpk  *
1345916cd2Sjpk  * When distributing Covered Code, include this CDDL HEADER in each
1445916cd2Sjpk  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1545916cd2Sjpk  * If applicable, add the following below this CDDL HEADER, with the
1645916cd2Sjpk  * fields enclosed by brackets "[]" replaced with your own identifying
1745916cd2Sjpk  * information: Portions Copyright [yyyy] [name of copyright owner]
1845916cd2Sjpk  *
1945916cd2Sjpk  * CDDL HEADER END
2045916cd2Sjpk  */
2145916cd2Sjpk /*
22*42096647STony Nguyen  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2345916cd2Sjpk  * Use is subject to license terms.
2445916cd2Sjpk  */
2545916cd2Sjpk 
2645916cd2Sjpk 
2745916cd2Sjpk /*
2845916cd2Sjpk  *	Miscellaneous user interfaces to trusted label functions.
2945916cd2Sjpk  *
3045916cd2Sjpk  */
3145916cd2Sjpk 
3245916cd2Sjpk 
3345916cd2Sjpk #include <ctype.h>
3445916cd2Sjpk #include <stdlib.h>
3545916cd2Sjpk #include <strings.h>
3645916cd2Sjpk 
3745916cd2Sjpk #include <sys/mman.h>
3845916cd2Sjpk 
3945916cd2Sjpk #include <tsol/label.h>
4045916cd2Sjpk 
4145916cd2Sjpk #include "labeld.h"
4245916cd2Sjpk #include "clnt.h"
4345916cd2Sjpk #include <sys/tsol/label_macro.h>
4445916cd2Sjpk #include <secdb.h>
4545916cd2Sjpk #include <user_attr.h>
4645916cd2Sjpk 
4745916cd2Sjpk static	bslabel_t slow, shigh;	/* static Admin Low and High SLs */
4845916cd2Sjpk static	bclear_t  clow, chigh;	/* static Admin Low and High CLRs */
4945916cd2Sjpk 
5045916cd2Sjpk static char color[MAXCOLOR];
5145916cd2Sjpk 
5245916cd2Sjpk 
5345916cd2Sjpk #define	incall callp->param.acall.cargs.inset_arg
5445916cd2Sjpk #define	inret callp->param.aret.rvals.inset_ret
5545916cd2Sjpk /*
5645916cd2Sjpk  *	blinset - Check in a label set.
5745916cd2Sjpk  *
5845916cd2Sjpk  *	Entry	label = Sensitivity Label to check.
5945916cd2Sjpk  *		id    = Label set identifier of set to check.
6045916cd2Sjpk  *
6145916cd2Sjpk  *	Exit	None.
6245916cd2Sjpk  *
6345916cd2Sjpk  *	Returns	-1, If label set unavailable, or server failure.
6445916cd2Sjpk  *		 0, If label not in label set.
6545916cd2Sjpk  *		 1, If label is in the label set.
6645916cd2Sjpk  *
6745916cd2Sjpk  *	Calls	__call_labeld(BLINSET), BLTYPE, BSLLOW, BSLHIGH.
6845916cd2Sjpk  *
6945916cd2Sjpk  *	Uses	slow, shigh.
7045916cd2Sjpk  */
7145916cd2Sjpk 
7245916cd2Sjpk int
blinset(const bslabel_t * label,const set_id * id)7345916cd2Sjpk blinset(const bslabel_t *label, const set_id *id)
7445916cd2Sjpk {
7545916cd2Sjpk 	if (id->type == SYSTEM_ACCREDITATION_RANGE) {
7645916cd2Sjpk 		if (!BLTYPE(&slow, SUN_SL_ID)) {
7745916cd2Sjpk 			/* initialize static labels. */
7845916cd2Sjpk 
7945916cd2Sjpk 			BSLLOW(&slow);
8045916cd2Sjpk 			BSLHIGH(&shigh);
8145916cd2Sjpk 		}
8245916cd2Sjpk 
8345916cd2Sjpk 		if (BLTYPE(label, SUN_SL_ID) &&
8445916cd2Sjpk 		    (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh)))
8545916cd2Sjpk 
8645916cd2Sjpk 			return (1);
8745916cd2Sjpk 	}
8845916cd2Sjpk 	if (id->type == USER_ACCREDITATION_RANGE ||
8945916cd2Sjpk 	    id->type == SYSTEM_ACCREDITATION_RANGE) {
9045916cd2Sjpk 		labeld_data_t	call;
9145916cd2Sjpk 		labeld_data_t	*callp = &call;
9245916cd2Sjpk 		size_t	bufsize = sizeof (labeld_data_t);
9345916cd2Sjpk 		size_t	datasize = CALL_SIZE(inset_call_t, 0);
9445916cd2Sjpk 
9545916cd2Sjpk 		call.callop = BLINSET;
9645916cd2Sjpk 		incall.label = *label;
9745916cd2Sjpk 		incall.type = id->type;
9845916cd2Sjpk 
9945916cd2Sjpk 		if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
10045916cd2Sjpk 			/* process error */
10145916cd2Sjpk 
10245916cd2Sjpk 			return (-1);
10345916cd2Sjpk 		}
10445916cd2Sjpk 		return (inret.inset);
10545916cd2Sjpk 	} else {
10645916cd2Sjpk 		/*
10745916cd2Sjpk 		 * Only System and User Accreditation Ranges presently
10845916cd2Sjpk 		 * implemented.
10945916cd2Sjpk 		 */
11045916cd2Sjpk 		return (-1);
11145916cd2Sjpk 	}
11245916cd2Sjpk }
11345916cd2Sjpk #undef	incall
11445916cd2Sjpk #undef	inret
11545916cd2Sjpk 
11645916cd2Sjpk #define	slvcall callp->param.acall.cargs.slvalid_arg
11745916cd2Sjpk #define	slvret callp->param.aret.rvals.slvalid_ret
11845916cd2Sjpk /*
11945916cd2Sjpk  *	bslvalid - Check Sensitivity Label for validity.
12045916cd2Sjpk  *
12145916cd2Sjpk  *	Entry	label = Sensitivity Label to check.
12245916cd2Sjpk  *
12345916cd2Sjpk  *	Exit	None.
12445916cd2Sjpk  *
12545916cd2Sjpk  *	Returns	-1, If unable to access label encodings file, or server failure.
12645916cd2Sjpk  *		 0, If label not valid.
12745916cd2Sjpk  *		 1, If label is valid.
12845916cd2Sjpk  *
12945916cd2Sjpk  *	Calls	__call_labeld(BSLVALID), BLTYPE, BSLLOW, BSLHIGH.
13045916cd2Sjpk  *
13145916cd2Sjpk  *	Uses	slow, shigh.
13245916cd2Sjpk  *
13345916cd2Sjpk  */
13445916cd2Sjpk 
13545916cd2Sjpk int
bslvalid(const bslabel_t * label)13645916cd2Sjpk bslvalid(const bslabel_t *label)
13745916cd2Sjpk {
13845916cd2Sjpk 	labeld_data_t	call;
13945916cd2Sjpk 	labeld_data_t	*callp = &call;
14045916cd2Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
14145916cd2Sjpk 	size_t	datasize = CALL_SIZE(slvalid_call_t, 0);
14245916cd2Sjpk 
14345916cd2Sjpk 	if (!BLTYPE(&slow, SUN_SL_ID)) {
14445916cd2Sjpk 		/* initialize static labels. */
14545916cd2Sjpk 
14645916cd2Sjpk 		BSLLOW(&slow);
14745916cd2Sjpk 		BSLHIGH(&shigh);
14845916cd2Sjpk 	}
14945916cd2Sjpk 
15045916cd2Sjpk 	if (BLTYPE(label, SUN_SL_ID) &&
15145916cd2Sjpk 	    (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh))) {
15245916cd2Sjpk 
15345916cd2Sjpk 		return (1);
15445916cd2Sjpk 	}
15545916cd2Sjpk 
15645916cd2Sjpk 	call.callop = BSLVALID;
15745916cd2Sjpk 	slvcall.label = *label;
15845916cd2Sjpk 
15945916cd2Sjpk 	if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
16045916cd2Sjpk 		/* process error */
16145916cd2Sjpk 
16245916cd2Sjpk 		return (-1);
16345916cd2Sjpk 	}
16445916cd2Sjpk 	return (slvret.valid);
16545916cd2Sjpk }
16645916cd2Sjpk #undef	slvcall
16745916cd2Sjpk #undef	slvret
16845916cd2Sjpk 
16945916cd2Sjpk #define	clrvcall callp->param.acall.cargs.clrvalid_arg
17045916cd2Sjpk #define	clrvret callp->param.aret.rvals.clrvalid_ret
17145916cd2Sjpk /*
17245916cd2Sjpk  *	bclearvalid - Check Clearance for validity.
17345916cd2Sjpk  *
17445916cd2Sjpk  *	Entry	clearance = Clearance to check.
17545916cd2Sjpk  *
17645916cd2Sjpk  *	Exit	None.
17745916cd2Sjpk  *
17845916cd2Sjpk  *	Returns	-1, If unable to access label encodings file, or server failure.
17945916cd2Sjpk  *		 0, If label not valid.
18045916cd2Sjpk  *		 1, If label is valid.
18145916cd2Sjpk  *
18245916cd2Sjpk  *	Calls	__call_labeld(BCLEARVALID), BLTYPE, BCLEARLOW, BCLEARHIGH.
18345916cd2Sjpk  *
18445916cd2Sjpk  *	Uses	clow, chigh.
18545916cd2Sjpk  *
18645916cd2Sjpk  */
18745916cd2Sjpk 
18845916cd2Sjpk int
bclearvalid(const bclear_t * clearance)18945916cd2Sjpk bclearvalid(const bclear_t *clearance)
19045916cd2Sjpk {
19145916cd2Sjpk 	labeld_data_t	call;
19245916cd2Sjpk 	labeld_data_t	*callp = &call;
19345916cd2Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
19445916cd2Sjpk 	size_t	datasize = CALL_SIZE(clrvalid_call_t, 0);
19545916cd2Sjpk 
19645916cd2Sjpk 	if (!BLTYPE(&clow, SUN_CLR_ID)) {
19745916cd2Sjpk 		/* initialize static labels. */
19845916cd2Sjpk 
19945916cd2Sjpk 		BCLEARLOW(&clow);
20045916cd2Sjpk 		BCLEARHIGH(&chigh);
20145916cd2Sjpk 	}
20245916cd2Sjpk 
20345916cd2Sjpk 	if (BLTYPE(clearance, SUN_CLR_ID) &&
20445916cd2Sjpk 	    (BLEQUAL(clearance, &clow) || BLEQUAL(clearance, &chigh))) {
20545916cd2Sjpk 
20645916cd2Sjpk 		return (1);
20745916cd2Sjpk 	}
20845916cd2Sjpk 
20945916cd2Sjpk 	call.callop = BCLEARVALID;
21045916cd2Sjpk 	clrvcall.clear = *clearance;
21145916cd2Sjpk 
21245916cd2Sjpk 	if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
21345916cd2Sjpk 		/* process error */
21445916cd2Sjpk 
21545916cd2Sjpk 		return (-1);
21645916cd2Sjpk 	}
21745916cd2Sjpk 	return (clrvret.valid);
21845916cd2Sjpk }
21945916cd2Sjpk #undef	clrvcall
22045916cd2Sjpk #undef	clrvret
22145916cd2Sjpk 
22245916cd2Sjpk #define	inforet callp->param.aret.rvals.info_ret
22345916cd2Sjpk /*
22445916cd2Sjpk  *	labelinfo - Get information about the label encodings file.
22545916cd2Sjpk  *
22645916cd2Sjpk  *	Entry	info = Address of label_info structure to update.
22745916cd2Sjpk  *
22845916cd2Sjpk  *	Exit	info = Updated.
22945916cd2Sjpk  *
23045916cd2Sjpk  *	Returns	-1, If unable to access label encodings file, or server failure.
23145916cd2Sjpk  *		 1, If successful.
23245916cd2Sjpk  *
23345916cd2Sjpk  *	Calls	__call_labeld(LABELINFO).
23445916cd2Sjpk  */
23545916cd2Sjpk 
23645916cd2Sjpk int
labelinfo(struct label_info * info)23745916cd2Sjpk labelinfo(struct label_info *info)
23845916cd2Sjpk {
23945916cd2Sjpk 	labeld_data_t	call;
24045916cd2Sjpk 	labeld_data_t	*callp = &call;
24145916cd2Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
24245916cd2Sjpk 	size_t	datasize = CALL_SIZE(info_call_t, 0);
24345916cd2Sjpk 	int	rval;
24445916cd2Sjpk 
24545916cd2Sjpk 	call.callop = LABELINFO;
24645916cd2Sjpk 
24745916cd2Sjpk 	if ((rval = __call_labeld(&callp, &bufsize, &datasize)) != SUCCESS) {
24845916cd2Sjpk 		/* process error */
24945916cd2Sjpk 
25045916cd2Sjpk 		return (-1);
25145916cd2Sjpk 	}
25245916cd2Sjpk 	*info = inforet.info;
25345916cd2Sjpk 	return (rval);
25445916cd2Sjpk }
25545916cd2Sjpk #undef	inforet
25645916cd2Sjpk 
25745916cd2Sjpk #define	lvret callp->param.aret.rvals.vers_ret
25845916cd2Sjpk /*
25945916cd2Sjpk  *	labelvers - Get version string of the label encodings file.
26045916cd2Sjpk  *
26145916cd2Sjpk  *	Entry	version = Address of string pointer to return.
26245916cd2Sjpk  *		len = Length of string if pre-allocated.
26345916cd2Sjpk  *
26445916cd2Sjpk  *	Exit	version = Updated.
26545916cd2Sjpk  *
26645916cd2Sjpk  *	Returns	-1, If unable to access label encodings file, or server failure.
26745916cd2Sjpk  *		 0, If unable to allocate version string,
26845916cd2Sjpk  *			or pre-allocated version string to short
26945916cd2Sjpk  *			(and **version = '\0').
27045916cd2Sjpk  *		length (including null) of version string, If successful.
27145916cd2Sjpk  *
27245916cd2Sjpk  *	Calls	__call_labeld(LABELVERS)
27345916cd2Sjpk  *			malloc, strlen.
27445916cd2Sjpk  */
27545916cd2Sjpk 
27645916cd2Sjpk ssize_t
labelvers(char ** version,size_t len)27745916cd2Sjpk labelvers(char **version, size_t len)
27845916cd2Sjpk {
27945916cd2Sjpk 	labeld_data_t	call;
28045916cd2Sjpk 	labeld_data_t	*callp = &call;
28145916cd2Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
28245916cd2Sjpk 	size_t	datasize = CALL_SIZE(vers_call_t, 0);
28345916cd2Sjpk 	size_t	ver_len;
28445916cd2Sjpk 
28545916cd2Sjpk 	call.callop = LABELVERS;
28645916cd2Sjpk 
28745916cd2Sjpk 	if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
28845916cd2Sjpk 
28945916cd2Sjpk 		if (callp != &call)
29045916cd2Sjpk 			/* release return buffer */
29145916cd2Sjpk 			(void) munmap((void *)callp, bufsize);
29245916cd2Sjpk 		return (-1);
29345916cd2Sjpk 	}
29445916cd2Sjpk 
29545916cd2Sjpk 	/* unpack length */
29645916cd2Sjpk 
29745916cd2Sjpk 	ver_len = strlen(lvret.vers) + 1;
29845916cd2Sjpk 	if (*version == NULL) {
29945916cd2Sjpk 		if ((*version = malloc(ver_len)) == NULL) {
30045916cd2Sjpk 			if (callp != &call)
30145916cd2Sjpk 				/* release return buffer */
30245916cd2Sjpk 				(void) munmap((void *)callp, bufsize);
30345916cd2Sjpk 			return (0);
30445916cd2Sjpk 		}
30545916cd2Sjpk 	} else if (ver_len > len) {
30645916cd2Sjpk 		**version = '\0';
30745916cd2Sjpk 		if (callp != &call)
30845916cd2Sjpk 			/* release return buffer */
30945916cd2Sjpk 			(void) munmap((void *)callp, bufsize);
31045916cd2Sjpk 		return (0);
31145916cd2Sjpk 	}
31245916cd2Sjpk 	(void) strcpy(*version, lvret.vers);
31345916cd2Sjpk 
31445916cd2Sjpk 	if (callp != &call)
31545916cd2Sjpk 		/* release return buffer */
31645916cd2Sjpk 		(void) munmap((void *)callp, bufsize);
31745916cd2Sjpk 	return (ver_len);
31845916cd2Sjpk }  /* labelvers */
31945916cd2Sjpk #undef	lvret
32045916cd2Sjpk 
32145916cd2Sjpk #define	ccall callp->param.acall.cargs.color_arg
32245916cd2Sjpk #define	cret callp->param.aret.rvals.color_ret
32345916cd2Sjpk /*
32445916cd2Sjpk  *	bltocolor - get ASCII color name of label.
32545916cd2Sjpk  *
32645916cd2Sjpk  *	Entry	label = Sensitivity Level of color to get.
32745916cd2Sjpk  *		size  = Size of the color_name array.
32845916cd2Sjpk  *		color_name = Storage for ASCII color name string to be returned.
32945916cd2Sjpk  *
33045916cd2Sjpk  *	Exit	None.
33145916cd2Sjpk  *
33245916cd2Sjpk  *	Returns	NULL, If error (label encodings file not accessible,
33345916cd2Sjpk  *			   invalid label, no color for this label).
33445916cd2Sjpk  *		Address of color_name parameter containing ASCII color name
33545916cd2Sjpk  *			defined for the label.
33645916cd2Sjpk  *
33745916cd2Sjpk  *	Calls	__call_labeld(BLTOCOLOR), strlen.
33845916cd2Sjpk  */
33945916cd2Sjpk 
34045916cd2Sjpk char *
bltocolor_r(const blevel_t * label,size_t size,char * color_name)34145916cd2Sjpk bltocolor_r(const blevel_t *label, size_t size, char *color_name)
34245916cd2Sjpk {
34345916cd2Sjpk 	labeld_data_t	call;
34445916cd2Sjpk 	labeld_data_t	*callp = &call;
34545916cd2Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
34645916cd2Sjpk 	size_t	datasize = CALL_SIZE(color_call_t, 0);
34745916cd2Sjpk 	char	*colorp;
34845916cd2Sjpk 
34945916cd2Sjpk 	call.callop = BLTOCOLOR;
35045916cd2Sjpk 	ccall.label = *label;
35145916cd2Sjpk 
35245916cd2Sjpk 	if ((__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) ||
35345916cd2Sjpk 	    (callp->reterr != 0) ||
35445916cd2Sjpk 	    (strlen(cret.color) >= size)) {
35545916cd2Sjpk 
35645916cd2Sjpk 		if (callp != &call)
35745916cd2Sjpk 			/* release return buffer */
35845916cd2Sjpk 			(void) munmap((void *)callp, bufsize);
35945916cd2Sjpk 		return (NULL);
36045916cd2Sjpk 	}
36145916cd2Sjpk 
36245916cd2Sjpk 	colorp = strcpy(color_name, cret.color);
36345916cd2Sjpk 
36445916cd2Sjpk 	if (callp != &call)
36545916cd2Sjpk 		/* release return buffer */
36645916cd2Sjpk 		(void) munmap((void *)callp, bufsize);
36745916cd2Sjpk 	return (colorp);
36845916cd2Sjpk }  /* bltocolor_r */
36945916cd2Sjpk #undef	ccall
37045916cd2Sjpk #undef	cret
37145916cd2Sjpk 
37245916cd2Sjpk /*
37345916cd2Sjpk  *	bltocolor - get ASCII color name of label.
37445916cd2Sjpk  *
37545916cd2Sjpk  *	Entry	label = Sensitivity Level of color to get.
37645916cd2Sjpk  *
37745916cd2Sjpk  *	Exit	None.
37845916cd2Sjpk  *
37945916cd2Sjpk  *	Returns	NULL, If error (label encodings file not accessible,
38045916cd2Sjpk  *			   invalid label, no color for this label).
38145916cd2Sjpk  *		Address of statically allocated string containing ASCII
38245916cd2Sjpk  *			color name defined for the classification contained
38345916cd2Sjpk  *			in label.
38445916cd2Sjpk  *
38545916cd2Sjpk  *	Uses	color.
38645916cd2Sjpk  *
38745916cd2Sjpk  *	Calls	bltocolor_r.
38845916cd2Sjpk  */
38945916cd2Sjpk 
39045916cd2Sjpk char *
bltocolor(const blevel_t * label)39145916cd2Sjpk bltocolor(const blevel_t *label)
39245916cd2Sjpk {
39345916cd2Sjpk 	return (bltocolor_r(label, sizeof (color), color));
39445916cd2Sjpk }  /* bltocolor */
39545916cd2Sjpk 
39645916cd2Sjpk blevel_t *
blabel_alloc(void)39745916cd2Sjpk blabel_alloc(void)
39845916cd2Sjpk {
39945916cd2Sjpk 	return (m_label_alloc(MAC_LABEL));
40045916cd2Sjpk }
40145916cd2Sjpk 
40245916cd2Sjpk void
blabel_free(blevel_t * label_p)40345916cd2Sjpk blabel_free(blevel_t *label_p)
40445916cd2Sjpk {
40545916cd2Sjpk 	free(label_p);
40645916cd2Sjpk }
40745916cd2Sjpk 
408*42096647STony Nguyen size32_t
blabel_size(void)40945916cd2Sjpk blabel_size(void)
41045916cd2Sjpk {
41145916cd2Sjpk 	return (sizeof (blevel_t));
41245916cd2Sjpk }
41345916cd2Sjpk 
41445916cd2Sjpk /*
41545916cd2Sjpk  *	getuserrange - get label range for user
41645916cd2Sjpk  *
41745916cd2Sjpk  *	Entry	username of user
41845916cd2Sjpk  *
41945916cd2Sjpk  *	Exit	None.
42045916cd2Sjpk  *
42145916cd2Sjpk  *	Returns	NULL, If memory allocation failure or userdefs failure.
42245916cd2Sjpk  *		otherwise returns the allocates m_range_t with the
42345916cd2Sjpk  *		user's min and max labels set.
42445916cd2Sjpk  */
42545916cd2Sjpk 
42645916cd2Sjpk m_range_t *
getuserrange(const char * username)42745916cd2Sjpk getuserrange(const char *username)
42845916cd2Sjpk {
42945916cd2Sjpk 	char		*kv_str = NULL;
43045916cd2Sjpk 	userattr_t 	*userp = NULL;
43145916cd2Sjpk 	m_range_t 	*range;
432aa2e15f6Srica 	m_label_t	*def_min, *def_clr;
43345916cd2Sjpk 
43445916cd2Sjpk 	/*
43545916cd2Sjpk 	 * Get some memory
43645916cd2Sjpk 	 */
43745916cd2Sjpk 
43845916cd2Sjpk 	if ((range = malloc(sizeof (m_range_t))) == NULL) {
43945916cd2Sjpk 		return (NULL);
44045916cd2Sjpk 	}
44145916cd2Sjpk 	if ((range->lower_bound = m_label_alloc(MAC_LABEL)) == NULL) {
44245916cd2Sjpk 		free(range);
44345916cd2Sjpk 		return (NULL);
44445916cd2Sjpk 	}
445aa2e15f6Srica 	def_min = range->lower_bound;
44645916cd2Sjpk 	if ((range->upper_bound = m_label_alloc(USER_CLEAR)) == NULL) {
44745916cd2Sjpk 		m_label_free(range->lower_bound);
44845916cd2Sjpk 		free(range);
44945916cd2Sjpk 		return (NULL);
45045916cd2Sjpk 	}
451aa2e15f6Srica 	def_clr = range->upper_bound;
452aa2e15f6Srica 
453aa2e15f6Srica 	/* If the user has an explicit min_label or clearance, use it. */
454aa2e15f6Srica 	if ((userp = getusernam(username)) != NULL) {
455aa2e15f6Srica 		if ((kv_str = kva_match(userp->attr, USERATTR_MINLABEL))
456aa2e15f6Srica 		    != NULL) {
457aa2e15f6Srica 			(void) str_to_label(kv_str, &range->lower_bound,
458aa2e15f6Srica 			    MAC_LABEL, L_NO_CORRECTION, NULL);
459aa2e15f6Srica 			def_min = NULL;		/* don't get default later */
460aa2e15f6Srica 		}
461aa2e15f6Srica 		if ((kv_str = kva_match(userp->attr, USERATTR_CLEARANCE))
462aa2e15f6Srica 		    != NULL) {
463aa2e15f6Srica 			(void) str_to_label(kv_str, &range->upper_bound,
464aa2e15f6Srica 			    USER_CLEAR, L_NO_CORRECTION, NULL);
465aa2e15f6Srica 			def_clr = NULL;		/* don't get default later */
466aa2e15f6Srica 		}
467aa2e15f6Srica 		free_userattr(userp);
468aa2e15f6Srica 	}
469aa2e15f6Srica 	if (def_min || def_clr) {
470aa2e15f6Srica 		/* Need to use system default clearance and/or min_label */
471aa2e15f6Srica 		if ((userdefs(def_min, def_clr)) == -1) {
47245916cd2Sjpk 			m_label_free(range->lower_bound);
47345916cd2Sjpk 			m_label_free(range->upper_bound);
47445916cd2Sjpk 			free(range);
47545916cd2Sjpk 			return (NULL);
47645916cd2Sjpk 		}
47745916cd2Sjpk 	}
478aa2e15f6Srica 
47945916cd2Sjpk 	return (range);
48045916cd2Sjpk }
481