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