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