11676Sjpk /*
21676Sjpk  * CDDL HEADER START
31676Sjpk  *
41676Sjpk  * The contents of this file are subject to the terms of the
51676Sjpk  * Common Development and Distribution License (the "License").
61676Sjpk  * You may not use this file except in compliance with the License.
71676Sjpk  *
81676Sjpk  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91676Sjpk  * or http://www.opensolaris.org/os/licensing.
101676Sjpk  * See the License for the specific language governing permissions
111676Sjpk  * and limitations under the License.
121676Sjpk  *
131676Sjpk  * When distributing Covered Code, include this CDDL HEADER in each
141676Sjpk  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151676Sjpk  * If applicable, add the following below this CDDL HEADER, with the
161676Sjpk  * fields enclosed by brackets "[]" replaced with your own identifying
171676Sjpk  * information: Portions Copyright [yyyy] [name of copyright owner]
181676Sjpk  *
191676Sjpk  * CDDL HEADER END
201676Sjpk  */
211676Sjpk /*
22*9112STon.Nguyen@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
231676Sjpk  * Use is subject to license terms.
241676Sjpk  */
251676Sjpk 
261676Sjpk 
271676Sjpk /*
281676Sjpk  *	Miscellaneous user interfaces to trusted label functions.
291676Sjpk  *
301676Sjpk  */
311676Sjpk 
321676Sjpk 
331676Sjpk #include <ctype.h>
341676Sjpk #include <stdlib.h>
351676Sjpk #include <strings.h>
361676Sjpk 
371676Sjpk #include <sys/mman.h>
381676Sjpk 
391676Sjpk #include <tsol/label.h>
401676Sjpk 
411676Sjpk #include "labeld.h"
421676Sjpk #include "clnt.h"
431676Sjpk #include <sys/tsol/label_macro.h>
441676Sjpk #include <secdb.h>
451676Sjpk #include <user_attr.h>
461676Sjpk 
471676Sjpk static	bslabel_t slow, shigh;	/* static Admin Low and High SLs */
481676Sjpk static	bclear_t  clow, chigh;	/* static Admin Low and High CLRs */
491676Sjpk 
501676Sjpk static char color[MAXCOLOR];
511676Sjpk 
521676Sjpk 
531676Sjpk #define	incall callp->param.acall.cargs.inset_arg
541676Sjpk #define	inret callp->param.aret.rvals.inset_ret
551676Sjpk /*
561676Sjpk  *	blinset - Check in a label set.
571676Sjpk  *
581676Sjpk  *	Entry	label = Sensitivity Label to check.
591676Sjpk  *		id    = Label set identifier of set to check.
601676Sjpk  *
611676Sjpk  *	Exit	None.
621676Sjpk  *
631676Sjpk  *	Returns	-1, If label set unavailable, or server failure.
641676Sjpk  *		 0, If label not in label set.
651676Sjpk  *		 1, If label is in the label set.
661676Sjpk  *
671676Sjpk  *	Calls	__call_labeld(BLINSET), BLTYPE, BSLLOW, BSLHIGH.
681676Sjpk  *
691676Sjpk  *	Uses	slow, shigh.
701676Sjpk  */
711676Sjpk 
721676Sjpk int
731676Sjpk blinset(const bslabel_t *label, const set_id *id)
741676Sjpk {
751676Sjpk 	if (id->type == SYSTEM_ACCREDITATION_RANGE) {
761676Sjpk 		if (!BLTYPE(&slow, SUN_SL_ID)) {
771676Sjpk 			/* initialize static labels. */
781676Sjpk 
791676Sjpk 			BSLLOW(&slow);
801676Sjpk 			BSLHIGH(&shigh);
811676Sjpk 		}
821676Sjpk 
831676Sjpk 		if (BLTYPE(label, SUN_SL_ID) &&
841676Sjpk 		    (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh)))
851676Sjpk 
861676Sjpk 			return (1);
871676Sjpk 	}
881676Sjpk 	if (id->type == USER_ACCREDITATION_RANGE ||
891676Sjpk 	    id->type == SYSTEM_ACCREDITATION_RANGE) {
901676Sjpk 		labeld_data_t	call;
911676Sjpk 		labeld_data_t	*callp = &call;
921676Sjpk 		size_t	bufsize = sizeof (labeld_data_t);
931676Sjpk 		size_t	datasize = CALL_SIZE(inset_call_t, 0);
941676Sjpk 
951676Sjpk 		call.callop = BLINSET;
961676Sjpk 		incall.label = *label;
971676Sjpk 		incall.type = id->type;
981676Sjpk 
991676Sjpk 		if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
1001676Sjpk 			/* process error */
1011676Sjpk 
1021676Sjpk 			return (-1);
1031676Sjpk 		}
1041676Sjpk 		return (inret.inset);
1051676Sjpk 	} else {
1061676Sjpk 		/*
1071676Sjpk 		 * Only System and User Accreditation Ranges presently
1081676Sjpk 		 * implemented.
1091676Sjpk 		 */
1101676Sjpk 		return (-1);
1111676Sjpk 	}
1121676Sjpk }
1131676Sjpk #undef	incall
1141676Sjpk #undef	inret
1151676Sjpk 
1161676Sjpk #define	slvcall callp->param.acall.cargs.slvalid_arg
1171676Sjpk #define	slvret callp->param.aret.rvals.slvalid_ret
1181676Sjpk /*
1191676Sjpk  *	bslvalid - Check Sensitivity Label for validity.
1201676Sjpk  *
1211676Sjpk  *	Entry	label = Sensitivity Label to check.
1221676Sjpk  *
1231676Sjpk  *	Exit	None.
1241676Sjpk  *
1251676Sjpk  *	Returns	-1, If unable to access label encodings file, or server failure.
1261676Sjpk  *		 0, If label not valid.
1271676Sjpk  *		 1, If label is valid.
1281676Sjpk  *
1291676Sjpk  *	Calls	__call_labeld(BSLVALID), BLTYPE, BSLLOW, BSLHIGH.
1301676Sjpk  *
1311676Sjpk  *	Uses	slow, shigh.
1321676Sjpk  *
1331676Sjpk  */
1341676Sjpk 
1351676Sjpk int
1361676Sjpk bslvalid(const bslabel_t *label)
1371676Sjpk {
1381676Sjpk 	labeld_data_t	call;
1391676Sjpk 	labeld_data_t	*callp = &call;
1401676Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
1411676Sjpk 	size_t	datasize = CALL_SIZE(slvalid_call_t, 0);
1421676Sjpk 
1431676Sjpk 	if (!BLTYPE(&slow, SUN_SL_ID)) {
1441676Sjpk 		/* initialize static labels. */
1451676Sjpk 
1461676Sjpk 		BSLLOW(&slow);
1471676Sjpk 		BSLHIGH(&shigh);
1481676Sjpk 	}
1491676Sjpk 
1501676Sjpk 	if (BLTYPE(label, SUN_SL_ID) &&
1511676Sjpk 	    (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh))) {
1521676Sjpk 
1531676Sjpk 		return (1);
1541676Sjpk 	}
1551676Sjpk 
1561676Sjpk 	call.callop = BSLVALID;
1571676Sjpk 	slvcall.label = *label;
1581676Sjpk 
1591676Sjpk 	if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
1601676Sjpk 		/* process error */
1611676Sjpk 
1621676Sjpk 		return (-1);
1631676Sjpk 	}
1641676Sjpk 	return (slvret.valid);
1651676Sjpk }
1661676Sjpk #undef	slvcall
1671676Sjpk #undef	slvret
1681676Sjpk 
1691676Sjpk #define	clrvcall callp->param.acall.cargs.clrvalid_arg
1701676Sjpk #define	clrvret callp->param.aret.rvals.clrvalid_ret
1711676Sjpk /*
1721676Sjpk  *	bclearvalid - Check Clearance for validity.
1731676Sjpk  *
1741676Sjpk  *	Entry	clearance = Clearance to check.
1751676Sjpk  *
1761676Sjpk  *	Exit	None.
1771676Sjpk  *
1781676Sjpk  *	Returns	-1, If unable to access label encodings file, or server failure.
1791676Sjpk  *		 0, If label not valid.
1801676Sjpk  *		 1, If label is valid.
1811676Sjpk  *
1821676Sjpk  *	Calls	__call_labeld(BCLEARVALID), BLTYPE, BCLEARLOW, BCLEARHIGH.
1831676Sjpk  *
1841676Sjpk  *	Uses	clow, chigh.
1851676Sjpk  *
1861676Sjpk  */
1871676Sjpk 
1881676Sjpk int
1891676Sjpk bclearvalid(const bclear_t *clearance)
1901676Sjpk {
1911676Sjpk 	labeld_data_t	call;
1921676Sjpk 	labeld_data_t	*callp = &call;
1931676Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
1941676Sjpk 	size_t	datasize = CALL_SIZE(clrvalid_call_t, 0);
1951676Sjpk 
1961676Sjpk 	if (!BLTYPE(&clow, SUN_CLR_ID)) {
1971676Sjpk 		/* initialize static labels. */
1981676Sjpk 
1991676Sjpk 		BCLEARLOW(&clow);
2001676Sjpk 		BCLEARHIGH(&chigh);
2011676Sjpk 	}
2021676Sjpk 
2031676Sjpk 	if (BLTYPE(clearance, SUN_CLR_ID) &&
2041676Sjpk 	    (BLEQUAL(clearance, &clow) || BLEQUAL(clearance, &chigh))) {
2051676Sjpk 
2061676Sjpk 		return (1);
2071676Sjpk 	}
2081676Sjpk 
2091676Sjpk 	call.callop = BCLEARVALID;
2101676Sjpk 	clrvcall.clear = *clearance;
2111676Sjpk 
2121676Sjpk 	if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
2131676Sjpk 		/* process error */
2141676Sjpk 
2151676Sjpk 		return (-1);
2161676Sjpk 	}
2171676Sjpk 	return (clrvret.valid);
2181676Sjpk }
2191676Sjpk #undef	clrvcall
2201676Sjpk #undef	clrvret
2211676Sjpk 
2221676Sjpk #define	inforet callp->param.aret.rvals.info_ret
2231676Sjpk /*
2241676Sjpk  *	labelinfo - Get information about the label encodings file.
2251676Sjpk  *
2261676Sjpk  *	Entry	info = Address of label_info structure to update.
2271676Sjpk  *
2281676Sjpk  *	Exit	info = Updated.
2291676Sjpk  *
2301676Sjpk  *	Returns	-1, If unable to access label encodings file, or server failure.
2311676Sjpk  *		 1, If successful.
2321676Sjpk  *
2331676Sjpk  *	Calls	__call_labeld(LABELINFO).
2341676Sjpk  */
2351676Sjpk 
2361676Sjpk int
2371676Sjpk labelinfo(struct label_info *info)
2381676Sjpk {
2391676Sjpk 	labeld_data_t	call;
2401676Sjpk 	labeld_data_t	*callp = &call;
2411676Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
2421676Sjpk 	size_t	datasize = CALL_SIZE(info_call_t, 0);
2431676Sjpk 	int	rval;
2441676Sjpk 
2451676Sjpk 	call.callop = LABELINFO;
2461676Sjpk 
2471676Sjpk 	if ((rval = __call_labeld(&callp, &bufsize, &datasize)) != SUCCESS) {
2481676Sjpk 		/* process error */
2491676Sjpk 
2501676Sjpk 		return (-1);
2511676Sjpk 	}
2521676Sjpk 	*info = inforet.info;
2531676Sjpk 	return (rval);
2541676Sjpk }
2551676Sjpk #undef	inforet
2561676Sjpk 
2571676Sjpk #define	lvret callp->param.aret.rvals.vers_ret
2581676Sjpk /*
2591676Sjpk  *	labelvers - Get version string of the label encodings file.
2601676Sjpk  *
2611676Sjpk  *	Entry	version = Address of string pointer to return.
2621676Sjpk  *		len = Length of string if pre-allocated.
2631676Sjpk  *
2641676Sjpk  *	Exit	version = Updated.
2651676Sjpk  *
2661676Sjpk  *	Returns	-1, If unable to access label encodings file, or server failure.
2671676Sjpk  *		 0, If unable to allocate version string,
2681676Sjpk  *			or pre-allocated version string to short
2691676Sjpk  *			(and **version = '\0').
2701676Sjpk  *		length (including null) of version string, If successful.
2711676Sjpk  *
2721676Sjpk  *	Calls	__call_labeld(LABELVERS)
2731676Sjpk  *			malloc, strlen.
2741676Sjpk  */
2751676Sjpk 
2761676Sjpk ssize_t
2771676Sjpk labelvers(char **version, size_t len)
2781676Sjpk {
2791676Sjpk 	labeld_data_t	call;
2801676Sjpk 	labeld_data_t	*callp = &call;
2811676Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
2821676Sjpk 	size_t	datasize = CALL_SIZE(vers_call_t, 0);
2831676Sjpk 	size_t	ver_len;
2841676Sjpk 
2851676Sjpk 	call.callop = LABELVERS;
2861676Sjpk 
2871676Sjpk 	if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
2881676Sjpk 
2891676Sjpk 		if (callp != &call)
2901676Sjpk 			/* release return buffer */
2911676Sjpk 			(void) munmap((void *)callp, bufsize);
2921676Sjpk 		return (-1);
2931676Sjpk 	}
2941676Sjpk 
2951676Sjpk 	/* unpack length */
2961676Sjpk 
2971676Sjpk 	ver_len = strlen(lvret.vers) + 1;
2981676Sjpk 	if (*version == NULL) {
2991676Sjpk 		if ((*version = malloc(ver_len)) == NULL) {
3001676Sjpk 			if (callp != &call)
3011676Sjpk 				/* release return buffer */
3021676Sjpk 				(void) munmap((void *)callp, bufsize);
3031676Sjpk 			return (0);
3041676Sjpk 		}
3051676Sjpk 	} else if (ver_len > len) {
3061676Sjpk 		**version = '\0';
3071676Sjpk 		if (callp != &call)
3081676Sjpk 			/* release return buffer */
3091676Sjpk 			(void) munmap((void *)callp, bufsize);
3101676Sjpk 		return (0);
3111676Sjpk 	}
3121676Sjpk 	(void) strcpy(*version, lvret.vers);
3131676Sjpk 
3141676Sjpk 	if (callp != &call)
3151676Sjpk 		/* release return buffer */
3161676Sjpk 		(void) munmap((void *)callp, bufsize);
3171676Sjpk 	return (ver_len);
3181676Sjpk }  /* labelvers */
3191676Sjpk #undef	lvret
3201676Sjpk 
3211676Sjpk #define	ccall callp->param.acall.cargs.color_arg
3221676Sjpk #define	cret callp->param.aret.rvals.color_ret
3231676Sjpk /*
3241676Sjpk  *	bltocolor - get ASCII color name of label.
3251676Sjpk  *
3261676Sjpk  *	Entry	label = Sensitivity Level of color to get.
3271676Sjpk  *		size  = Size of the color_name array.
3281676Sjpk  *		color_name = Storage for ASCII color name string to be returned.
3291676Sjpk  *
3301676Sjpk  *	Exit	None.
3311676Sjpk  *
3321676Sjpk  *	Returns	NULL, If error (label encodings file not accessible,
3331676Sjpk  *			   invalid label, no color for this label).
3341676Sjpk  *		Address of color_name parameter containing ASCII color name
3351676Sjpk  *			defined for the label.
3361676Sjpk  *
3371676Sjpk  *	Calls	__call_labeld(BLTOCOLOR), strlen.
3381676Sjpk  */
3391676Sjpk 
3401676Sjpk char *
3411676Sjpk bltocolor_r(const blevel_t *label, size_t size, char *color_name)
3421676Sjpk {
3431676Sjpk 	labeld_data_t	call;
3441676Sjpk 	labeld_data_t	*callp = &call;
3451676Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
3461676Sjpk 	size_t	datasize = CALL_SIZE(color_call_t, 0);
3471676Sjpk 	char	*colorp;
3481676Sjpk 
3491676Sjpk 	call.callop = BLTOCOLOR;
3501676Sjpk 	ccall.label = *label;
3511676Sjpk 
3521676Sjpk 	if ((__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) ||
3531676Sjpk 	    (callp->reterr != 0) ||
3541676Sjpk 	    (strlen(cret.color) >= size)) {
3551676Sjpk 
3561676Sjpk 		if (callp != &call)
3571676Sjpk 			/* release return buffer */
3581676Sjpk 			(void) munmap((void *)callp, bufsize);
3591676Sjpk 		return (NULL);
3601676Sjpk 	}
3611676Sjpk 
3621676Sjpk 	colorp = strcpy(color_name, cret.color);
3631676Sjpk 
3641676Sjpk 	if (callp != &call)
3651676Sjpk 		/* release return buffer */
3661676Sjpk 		(void) munmap((void *)callp, bufsize);
3671676Sjpk 	return (colorp);
3681676Sjpk }  /* bltocolor_r */
3691676Sjpk #undef	ccall
3701676Sjpk #undef	cret
3711676Sjpk 
3721676Sjpk /*
3731676Sjpk  *	bltocolor - get ASCII color name of label.
3741676Sjpk  *
3751676Sjpk  *	Entry	label = Sensitivity Level of color to get.
3761676Sjpk  *
3771676Sjpk  *	Exit	None.
3781676Sjpk  *
3791676Sjpk  *	Returns	NULL, If error (label encodings file not accessible,
3801676Sjpk  *			   invalid label, no color for this label).
3811676Sjpk  *		Address of statically allocated string containing ASCII
3821676Sjpk  *			color name defined for the classification contained
3831676Sjpk  *			in label.
3841676Sjpk  *
3851676Sjpk  *	Uses	color.
3861676Sjpk  *
3871676Sjpk  *	Calls	bltocolor_r.
3881676Sjpk  */
3891676Sjpk 
3901676Sjpk char *
3911676Sjpk bltocolor(const blevel_t *label)
3921676Sjpk {
3931676Sjpk 	return (bltocolor_r(label, sizeof (color), color));
3941676Sjpk }  /* bltocolor */
3951676Sjpk 
3961676Sjpk blevel_t *
3971676Sjpk blabel_alloc(void)
3981676Sjpk {
3991676Sjpk 	return (m_label_alloc(MAC_LABEL));
4001676Sjpk }
4011676Sjpk 
4021676Sjpk void
4031676Sjpk blabel_free(blevel_t *label_p)
4041676Sjpk {
4051676Sjpk 	free(label_p);
4061676Sjpk }
4071676Sjpk 
408*9112STon.Nguyen@Sun.COM size32_t
4091676Sjpk blabel_size(void)
4101676Sjpk {
4111676Sjpk 	return (sizeof (blevel_t));
4121676Sjpk }
4131676Sjpk 
4141676Sjpk /*
4151676Sjpk  *	getuserrange - get label range for user
4161676Sjpk  *
4171676Sjpk  *	Entry	username of user
4181676Sjpk  *
4191676Sjpk  *	Exit	None.
4201676Sjpk  *
4211676Sjpk  *	Returns	NULL, If memory allocation failure or userdefs failure.
4221676Sjpk  *		otherwise returns the allocates m_range_t with the
4231676Sjpk  *		user's min and max labels set.
4241676Sjpk  */
4251676Sjpk 
4261676Sjpk m_range_t *
4271676Sjpk getuserrange(const char *username)
4281676Sjpk {
4291676Sjpk 	char		*kv_str = NULL;
4301676Sjpk 	userattr_t 	*userp = NULL;
4311676Sjpk 	m_range_t 	*range;
4322664Srica 	m_label_t	*def_min, *def_clr;
4331676Sjpk 
4341676Sjpk 	/*
4351676Sjpk 	 * Get some memory
4361676Sjpk 	 */
4371676Sjpk 
4381676Sjpk 	if ((range = malloc(sizeof (m_range_t))) == NULL) {
4391676Sjpk 		return (NULL);
4401676Sjpk 	}
4411676Sjpk 	if ((range->lower_bound = m_label_alloc(MAC_LABEL)) == NULL) {
4421676Sjpk 		free(range);
4431676Sjpk 		return (NULL);
4441676Sjpk 	}
4452664Srica 	def_min = range->lower_bound;
4461676Sjpk 	if ((range->upper_bound = m_label_alloc(USER_CLEAR)) == NULL) {
4471676Sjpk 		m_label_free(range->lower_bound);
4481676Sjpk 		free(range);
4491676Sjpk 		return (NULL);
4501676Sjpk 	}
4512664Srica 	def_clr = range->upper_bound;
4522664Srica 
4532664Srica 	/* If the user has an explicit min_label or clearance, use it. */
4542664Srica 	if ((userp = getusernam(username)) != NULL) {
4552664Srica 		if ((kv_str = kva_match(userp->attr, USERATTR_MINLABEL))
4562664Srica 		    != NULL) {
4572664Srica 			(void) str_to_label(kv_str, &range->lower_bound,
4582664Srica 			    MAC_LABEL, L_NO_CORRECTION, NULL);
4592664Srica 			def_min = NULL;		/* don't get default later */
4602664Srica 		}
4612664Srica 		if ((kv_str = kva_match(userp->attr, USERATTR_CLEARANCE))
4622664Srica 		    != NULL) {
4632664Srica 			(void) str_to_label(kv_str, &range->upper_bound,
4642664Srica 			    USER_CLEAR, L_NO_CORRECTION, NULL);
4652664Srica 			def_clr = NULL;		/* don't get default later */
4662664Srica 		}
4672664Srica 		free_userattr(userp);
4681676Sjpk 	}
4692664Srica 	if (def_min || def_clr) {
4702664Srica 		/* Need to use system default clearance and/or min_label */
4712664Srica 		if ((userdefs(def_min, def_clr)) == -1) {
4722664Srica 			m_label_free(range->lower_bound);
4732664Srica 			m_label_free(range->upper_bound);
4742664Srica 			free(range);
4752664Srica 			return (NULL);
4762664Srica 		}
4771676Sjpk 	}
4782664Srica 
4791676Sjpk 	return (range);
4801676Sjpk }
481