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