xref: /illumos-gate/usr/src/common/tsol/ltos.c (revision 4201a95e)
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 #if !defined(_KERNEL)
27 #include <errno.h>
28 #endif /* !defined(_KERNEL) */
29 
30 #include <sys/types.h>
31 #include <sys/mman.h>
32 #include <sys/tsol/label_macro.h>
33 
34 #include <sys/tsol/label.h>
35 
36 #if !defined(_KERNEL)
37 #include "clnt.h"
38 #include "labeld.h"
39 #endif /* !defined(_KERNEL) */
40 
41 #if defined(_KERNEL)
42 #include <sys/systm.h>
43 #include <sys/sunddi.h>
44 #else
45 #include <stdlib.h>
46 #include <string.h>
47 #include <ctype.h>
48 #endif
49 
50 
51 
52 static _mac_label_impl_t low;
53 static _mac_label_impl_t high;
54 static int	inited = 0;
55 
56 #if defined(_KERNEL)
57 #define	malloc(l)	kmem_alloc(l, KM_NOSLEEP)
58 #define	freeit(a, l)		kmem_free(a, l)
59 #else /* defined(_KERNEL) */
60 #define	freeit(a, l)		free(a)
61 #endif /* defined(_KERNEL) */
62 
63 /* 0x + Classification + '-' + ll + '-' + Compartments + end of string */
64 #define	_HEX_SIZE 2+(sizeof (Classification_t)*2)+4+\
65 	(sizeof (Compartments_t)*2)+1
66 
67 /* 0x + Classification + '-' + ll + '-' + end of string */
68 #define	_MIN_HEX (2 + (sizeof (Classification_t)*2) + 4 + 1)
69 
70 static char digits[] = "0123456789abcdef";
71 
72 #define	HEX(h, i, l, s) \
73 	for (; i < s; /* */) {\
74 	h[i++] = digits[(unsigned int)(*l >> 4)];\
75 	h[i++] = digits[(unsigned int)(*l++&0xF)]; }
76 
77 static int
__hex(char ** s,const m_label_t * l)78 __hex(char **s, const m_label_t *l)
79 {
80 	char	*hex;
81 	int	i = 0;
82 	uchar_t *hl;
83 	int	hex_len;
84 	uchar_t *len;
85 
86 	hl = (uchar_t  *)&(((_mac_label_impl_t *)l)->_c_len);
87 	len = hl;
88 
89 	if (*len == 0) {
90 		/* old binary label */
91 		hex_len = _HEX_SIZE;
92 	} else {
93 		hex_len = _MIN_HEX + (*len * sizeof (uint32_t) * 2);
94 	}
95 
96 	if ((hex = malloc(hex_len)) == NULL) {
97 		return (-1);
98 	}
99 
100 	/* header */
101 
102 	hex[i++] = '0';
103 	hex[i++] = 'x';
104 
105 	/* classification */
106 
107 	hl++;		/* start at classification */
108 	HEX(hex, i, hl, 6);
109 
110 	/* Add compartments length */
111 	hex[i++] = '-';
112 	HEX(hex, i, len, 9);
113 	hex[i++] = '-';
114 
115 	/* compartments */
116 	HEX(hex, i, hl, hex_len-1);
117 	hex[i] = '\0';
118 
119 	/* truncate trailing zeros */
120 
121 	while (hex[i-1] == '0' && hex[i-2] == '0') {
122 		i -= 2;
123 	}
124 	hex[i] = '\0';
125 
126 	if ((*s = strdup(hex)) == NULL) {
127 		freeit(hex, hex_len);
128 		return (-1);
129 	}
130 
131 	freeit(hex, hex_len);
132 	return (0);
133 
134 }
135 
136 int
l_to_str_internal(const m_label_t * l,char ** s)137 l_to_str_internal(const m_label_t *l, char **s)
138 {
139 	if (inited == 0) {
140 		inited = 1;
141 		_BSLLOW(&low);
142 		_BSLHIGH(&high);
143 	}
144 
145 	if (!(_MTYPE(l, SUN_MAC_ID) || _MTYPE(l, SUN_UCLR_ID))) {
146 #if !defined(_KERNEL)
147 		errno = EINVAL;
148 #endif /* !defined(_KERNEL) */
149 		*s = NULL;
150 		return (-1);
151 	}
152 	if (_MEQUAL(&low, (_mac_label_impl_t *)l)) {
153 		if ((*s = strdup(ADMIN_LOW)) == NULL) {
154 			return (-1);
155 		}
156 		return (0);
157 	}
158 	if (_MEQUAL(&high, (_mac_label_impl_t *)l)) {
159 		if ((*s = strdup(ADMIN_HIGH)) == NULL) {
160 			return (-1);
161 		}
162 		return (0);
163 	}
164 
165 	return (__hex(s, l));
166 }
167 
168 #if !defined(_KERNEL)
169 /*
170  * label_to_str -- convert a label to the requested type of string.
171  *
172  *	Entry	l = label to convert;
173  *		t = type of conversion;
174  *		f = flags for conversion type;
175  *
176  *	Exit	*s = allocated converted string;
177  *		     Caller must call free() to free.
178  *
179  *	Returns	0, success.
180  *		-1, error, errno set; *s = NULL.
181  *
182  *	Calls	labeld
183  */
184 
185 int
label_to_str(const m_label_t * l,char ** s,const m_label_str_t t,uint_t f)186 label_to_str(const m_label_t *l, char **s, const m_label_str_t t, uint_t f)
187 {
188 	labeld_data_t	call;
189 	labeld_data_t	*callp = &call;
190 	size_t	bufsize = sizeof (labeld_data_t);
191 	size_t	datasize;
192 	int	err;
193 	int	string_start = 0;
194 
195 	if (inited == 0) {
196 		inited = 1;
197 		_BSLLOW(&low);
198 		_BSLHIGH(&high);
199 	}
200 
201 #define	lscall callp->param.acall.cargs.ls_arg
202 #define	lsret callp->param.aret.rvals.ls_ret
203 	switch (t) {
204 	case M_LABEL:
205 		call.callop = LTOS;
206 		lscall.label = *l;
207 		lscall.flags = f;
208 		datasize = CALL_SIZE(ls_call_t, 0);
209 		if ((err = __call_labeld(&callp, &bufsize, &datasize)) ==
210 		    SUCCESS) {
211 			if (callp->reterr != 0) {
212 				errno = EINVAL;
213 				*s = NULL;
214 				return (-1);
215 			}
216 			*s = strdup(lsret.buf);
217 			if (callp != &call) {
218 				/* release returned buffer */
219 				(void) munmap((void *)callp, bufsize);
220 			}
221 			if (*s == NULL) {
222 				return (-1);
223 			}
224 			return (0);
225 		}
226 		switch (err) {
227 		case NOSERVER:
228 			/* server not present */
229 			/* special case admin_low and admin_high */
230 
231 			if (_MEQUAL(&low, (_mac_label_impl_t *)l)) {
232 				if ((*s = strdup(ADMIN_LOW)) == NULL) {
233 					return (-1);
234 				}
235 				return (0);
236 			} else if (_MEQUAL(&high, (_mac_label_impl_t *)l)) {
237 				if ((*s = strdup(ADMIN_HIGH)) == NULL) {
238 					return (-1);
239 				}
240 				return (0);
241 			}
242 			errno = ENOTSUP;
243 			break;
244 		default:
245 			errno = EINVAL;
246 			break;
247 		}
248 		*s = NULL;
249 		return (-1);
250 #undef	lscall
251 #undef	lsret
252 
253 	case M_INTERNAL: {
254 		return (l_to_str_internal(l, s));
255 	}
256 
257 #define	ccall callp->param.acall.cargs.color_arg
258 #define	cret callp->param.aret.rvals.color_ret
259 	case M_COLOR:
260 		datasize = CALL_SIZE(color_call_t, 0);
261 		call.callop = BLTOCOLOR;
262 		ccall.label = *l;
263 
264 		if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
265 			if (callp->reterr != 0) {
266 				errno = EINVAL;
267 				*s = NULL;
268 				return (-1);
269 			}
270 			*s = strdup(cret.color);
271 			if (callp != &call) {
272 				/* release returned buffer */
273 				(void) munmap((void *)callp, bufsize);
274 			}
275 			if (*s == NULL) {
276 				return (-1);
277 			}
278 			return (0);
279 		} else {
280 			errno = ENOTSUP;
281 			*s = NULL;
282 			return (-1);
283 		}
284 #undef	ccall
285 #undef	cret
286 
287 #define	prcall	callp->param.acall.cargs.pr_arg
288 #define	prret	callp->param.aret.rvals.pr_ret
289 	case PRINTER_TOP_BOTTOM:
290 		call.callop = PR_TOP;
291 		break;
292 	case PRINTER_LABEL:
293 		call.callop = PR_LABEL;
294 		break;
295 	case PRINTER_CAVEATS:
296 		call.callop = PR_CAVEATS;
297 		string_start = 1;	/* compensate for leading space */
298 		break;
299 	case PRINTER_CHANNELS:
300 		call.callop = PR_CHANNELS;
301 		string_start = 1;	/* compensate for leading space */
302 		break;
303 	default:
304 		errno = EINVAL;
305 		*s = NULL;
306 		return (-1);
307 	}
308 	/* do the common printer calls */
309 	datasize = CALL_SIZE(pr_call_t, 0);
310 	prcall.label = *l;
311 	prcall.flags = f;
312 	if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
313 		if (callp->reterr != 0) {
314 			errno = EINVAL;
315 			*s = NULL;
316 			return (-1);
317 		}
318 		*s = strdup(&prret.buf[string_start]);
319 		if (callp != &call) {
320 			/* release returned buffer */
321 			(void) munmap((void *)callp, bufsize);
322 		}
323 		if (*s == NULL) {
324 			return (-1);
325 		}
326 		return (0);
327 	} else {
328 		errno = ENOTSUP;
329 		*s = NULL;
330 		return (-1);
331 	}
332 #undef	prcall
333 #undef	prret
334 }
335 #endif /* !defined(_KERNEL) */
336