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
47static	bslabel_t slow, shigh;	/* static Admin Low and High SLs */
48static	bclear_t  clow, chigh;	/* static Admin Low and High CLRs */
49
50static 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
72int
73blinset(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
135int
136bslvalid(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
188int
189bclearvalid(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
236int
237labelinfo(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
276ssize_t
277labelvers(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
340char *
341bltocolor_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
390char *
391bltocolor(const blevel_t *label)
392{
393	return (bltocolor_r(label, sizeof (color), color));
394}  /* bltocolor */
395
396blevel_t *
397blabel_alloc(void)
398{
399	return (m_label_alloc(MAC_LABEL));
400}
401
402void
403blabel_free(blevel_t *label_p)
404{
405	free(label_p);
406}
407
408size32_t
409blabel_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
426m_range_t *
427getuserrange(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