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