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