xref: /illumos-gate/usr/src/common/tsol/ltos.c (revision 4201a95e)
145916cd2Sjpk /*
245916cd2Sjpk  * CDDL HEADER START
345916cd2Sjpk  *
445916cd2Sjpk  * The contents of this file are subject to the terms of the
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * You may not use this file except in compliance with the License.
745916cd2Sjpk  *
845916cd2Sjpk  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
945916cd2Sjpk  * or http://www.opensolaris.org/os/licensing.
1045916cd2Sjpk  * See the License for the specific language governing permissions
1145916cd2Sjpk  * and limitations under the License.
1245916cd2Sjpk  *
1345916cd2Sjpk  * When distributing Covered Code, include this CDDL HEADER in each
1445916cd2Sjpk  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1545916cd2Sjpk  * If applicable, add the following below this CDDL HEADER, with the
1645916cd2Sjpk  * fields enclosed by brackets "[]" replaced with your own identifying
1745916cd2Sjpk  * information: Portions Copyright [yyyy] [name of copyright owner]
1845916cd2Sjpk  *
1945916cd2Sjpk  * CDDL HEADER END
2045916cd2Sjpk  */
2145916cd2Sjpk /*
22*4201a95eSRic Aleshire  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2345916cd2Sjpk  * Use is subject to license terms.
2445916cd2Sjpk  */
2545916cd2Sjpk 
26*4201a95eSRic Aleshire #if !defined(_KERNEL)
2745916cd2Sjpk #include <errno.h>
28*4201a95eSRic Aleshire #endif /* !defined(_KERNEL) */
2945916cd2Sjpk 
3045916cd2Sjpk #include <sys/types.h>
31*4201a95eSRic Aleshire #include <sys/mman.h>
3245916cd2Sjpk #include <sys/tsol/label_macro.h>
3345916cd2Sjpk 
34*4201a95eSRic Aleshire #include <sys/tsol/label.h>
3545916cd2Sjpk 
36*4201a95eSRic Aleshire #if !defined(_KERNEL)
3745916cd2Sjpk #include "clnt.h"
3845916cd2Sjpk #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 
5145916cd2Sjpk 
5245916cd2Sjpk static _mac_label_impl_t low;
5345916cd2Sjpk static _mac_label_impl_t high;
5445916cd2Sjpk static int	inited = 0;
5545916cd2Sjpk 
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 
6345916cd2Sjpk /* 0x + Classification + '-' + ll + '-' + Compartments + end of string */
6445916cd2Sjpk #define	_HEX_SIZE 2+(sizeof (Classification_t)*2)+4+\
6545916cd2Sjpk 	(sizeof (Compartments_t)*2)+1
6645916cd2Sjpk 
6745916cd2Sjpk /* 0x + Classification + '-' + ll + '-' + end of string */
6845916cd2Sjpk #define	_MIN_HEX (2 + (sizeof (Classification_t)*2) + 4 + 1)
6945916cd2Sjpk 
7045916cd2Sjpk static char digits[] = "0123456789abcdef";
7145916cd2Sjpk 
7245916cd2Sjpk #define	HEX(h, i, l, s) \
7345916cd2Sjpk 	for (; i < s; /* */) {\
7445916cd2Sjpk 	h[i++] = digits[(unsigned int)(*l >> 4)];\
7545916cd2Sjpk 	h[i++] = digits[(unsigned int)(*l++&0xF)]; }
7645916cd2Sjpk 
7745916cd2Sjpk static int
__hex(char ** s,const m_label_t * l)7845916cd2Sjpk __hex(char **s, const m_label_t *l)
7945916cd2Sjpk {
8045916cd2Sjpk 	char	*hex;
8145916cd2Sjpk 	int	i = 0;
8245916cd2Sjpk 	uchar_t *hl;
8345916cd2Sjpk 	int	hex_len;
8445916cd2Sjpk 	uchar_t *len;
8545916cd2Sjpk 
8645916cd2Sjpk 	hl = (uchar_t  *)&(((_mac_label_impl_t *)l)->_c_len);
8745916cd2Sjpk 	len = hl;
8845916cd2Sjpk 
8945916cd2Sjpk 	if (*len == 0) {
9045916cd2Sjpk 		/* old binary label */
9145916cd2Sjpk 		hex_len = _HEX_SIZE;
9245916cd2Sjpk 	} else {
9345916cd2Sjpk 		hex_len = _MIN_HEX + (*len * sizeof (uint32_t) * 2);
9445916cd2Sjpk 	}
9545916cd2Sjpk 
9645916cd2Sjpk 	if ((hex = malloc(hex_len)) == NULL) {
9745916cd2Sjpk 		return (-1);
9845916cd2Sjpk 	}
9945916cd2Sjpk 
10045916cd2Sjpk 	/* header */
10145916cd2Sjpk 
10245916cd2Sjpk 	hex[i++] = '0';
10345916cd2Sjpk 	hex[i++] = 'x';
10445916cd2Sjpk 
10545916cd2Sjpk 	/* classification */
10645916cd2Sjpk 
10745916cd2Sjpk 	hl++;		/* start at classification */
10845916cd2Sjpk 	HEX(hex, i, hl, 6);
10945916cd2Sjpk 
11045916cd2Sjpk 	/* Add compartments length */
11145916cd2Sjpk 	hex[i++] = '-';
11245916cd2Sjpk 	HEX(hex, i, len, 9);
11345916cd2Sjpk 	hex[i++] = '-';
11445916cd2Sjpk 
11545916cd2Sjpk 	/* compartments */
11645916cd2Sjpk 	HEX(hex, i, hl, hex_len-1);
11745916cd2Sjpk 	hex[i] = '\0';
11845916cd2Sjpk 
11945916cd2Sjpk 	/* truncate trailing zeros */
12045916cd2Sjpk 
12145916cd2Sjpk 	while (hex[i-1] == '0' && hex[i-2] == '0') {
12245916cd2Sjpk 		i -= 2;
12345916cd2Sjpk 	}
12445916cd2Sjpk 	hex[i] = '\0';
12545916cd2Sjpk 
12645916cd2Sjpk 	if ((*s = strdup(hex)) == NULL) {
127*4201a95eSRic Aleshire 		freeit(hex, hex_len);
12845916cd2Sjpk 		return (-1);
12945916cd2Sjpk 	}
13045916cd2Sjpk 
131*4201a95eSRic Aleshire 	freeit(hex, hex_len);
13245916cd2Sjpk 	return (0);
13345916cd2Sjpk 
13445916cd2Sjpk }
13545916cd2Sjpk 
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)
16945916cd2Sjpk /*
17045916cd2Sjpk  * label_to_str -- convert a label to the requested type of string.
17145916cd2Sjpk  *
17245916cd2Sjpk  *	Entry	l = label to convert;
17345916cd2Sjpk  *		t = type of conversion;
17445916cd2Sjpk  *		f = flags for conversion type;
17545916cd2Sjpk  *
17645916cd2Sjpk  *	Exit	*s = allocated converted string;
17745916cd2Sjpk  *		     Caller must call free() to free.
17845916cd2Sjpk  *
17945916cd2Sjpk  *	Returns	0, success.
18045916cd2Sjpk  *		-1, error, errno set; *s = NULL.
18145916cd2Sjpk  *
18245916cd2Sjpk  *	Calls	labeld
18345916cd2Sjpk  */
18445916cd2Sjpk 
18545916cd2Sjpk int
label_to_str(const m_label_t * l,char ** s,const m_label_str_t t,uint_t f)18645916cd2Sjpk label_to_str(const m_label_t *l, char **s, const m_label_str_t t, uint_t f)
18745916cd2Sjpk {
18845916cd2Sjpk 	labeld_data_t	call;
18945916cd2Sjpk 	labeld_data_t	*callp = &call;
19045916cd2Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
19145916cd2Sjpk 	size_t	datasize;
19245916cd2Sjpk 	int	err;
1933851ea85Sgww 	int	string_start = 0;
19445916cd2Sjpk 
19545916cd2Sjpk 	if (inited == 0) {
19645916cd2Sjpk 		inited = 1;
19745916cd2Sjpk 		_BSLLOW(&low);
19845916cd2Sjpk 		_BSLHIGH(&high);
19945916cd2Sjpk 	}
20045916cd2Sjpk 
20145916cd2Sjpk #define	lscall callp->param.acall.cargs.ls_arg
20245916cd2Sjpk #define	lsret callp->param.aret.rvals.ls_ret
20345916cd2Sjpk 	switch (t) {
20445916cd2Sjpk 	case M_LABEL:
20545916cd2Sjpk 		call.callop = LTOS;
20645916cd2Sjpk 		lscall.label = *l;
20745916cd2Sjpk 		lscall.flags = f;
20845916cd2Sjpk 		datasize = CALL_SIZE(ls_call_t, 0);
20945916cd2Sjpk 		if ((err = __call_labeld(&callp, &bufsize, &datasize)) ==
21045916cd2Sjpk 		    SUCCESS) {
21145916cd2Sjpk 			if (callp->reterr != 0) {
21245916cd2Sjpk 				errno = EINVAL;
21345916cd2Sjpk 				*s = NULL;
21445916cd2Sjpk 				return (-1);
21545916cd2Sjpk 			}
2163851ea85Sgww 			*s = strdup(lsret.buf);
21745916cd2Sjpk 			if (callp != &call) {
21845916cd2Sjpk 				/* release returned buffer */
21945916cd2Sjpk 				(void) munmap((void *)callp, bufsize);
22045916cd2Sjpk 			}
2213851ea85Sgww 			if (*s == NULL) {
2223851ea85Sgww 				return (-1);
2233851ea85Sgww 			}
22445916cd2Sjpk 			return (0);
22545916cd2Sjpk 		}
22645916cd2Sjpk 		switch (err) {
22745916cd2Sjpk 		case NOSERVER:
22845916cd2Sjpk 			/* server not present */
22945916cd2Sjpk 			/* special case admin_low and admin_high */
23045916cd2Sjpk 
23145916cd2Sjpk 			if (_MEQUAL(&low, (_mac_label_impl_t *)l)) {
23245916cd2Sjpk 				if ((*s = strdup(ADMIN_LOW)) == NULL) {
23345916cd2Sjpk 					return (-1);
23445916cd2Sjpk 				}
23545916cd2Sjpk 				return (0);
23645916cd2Sjpk 			} else if (_MEQUAL(&high, (_mac_label_impl_t *)l)) {
23745916cd2Sjpk 				if ((*s = strdup(ADMIN_HIGH)) == NULL) {
23845916cd2Sjpk 					return (-1);
23945916cd2Sjpk 				}
24045916cd2Sjpk 				return (0);
24145916cd2Sjpk 			}
24245916cd2Sjpk 			errno = ENOTSUP;
24345916cd2Sjpk 			break;
24445916cd2Sjpk 		default:
24545916cd2Sjpk 			errno = EINVAL;
24645916cd2Sjpk 			break;
24745916cd2Sjpk 		}
24845916cd2Sjpk 		*s = NULL;
24945916cd2Sjpk 		return (-1);
25045916cd2Sjpk #undef	lscall
25145916cd2Sjpk #undef	lsret
25245916cd2Sjpk 
25345916cd2Sjpk 	case M_INTERNAL: {
254*4201a95eSRic Aleshire 		return (l_to_str_internal(l, s));
25545916cd2Sjpk 	}
25645916cd2Sjpk 
25745916cd2Sjpk #define	ccall callp->param.acall.cargs.color_arg
25845916cd2Sjpk #define	cret callp->param.aret.rvals.color_ret
25945916cd2Sjpk 	case M_COLOR:
26045916cd2Sjpk 		datasize = CALL_SIZE(color_call_t, 0);
26145916cd2Sjpk 		call.callop = BLTOCOLOR;
26245916cd2Sjpk 		ccall.label = *l;
26345916cd2Sjpk 
2643851ea85Sgww 		if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
2653851ea85Sgww 			if (callp->reterr != 0) {
2663851ea85Sgww 				errno = EINVAL;
2673851ea85Sgww 				*s = NULL;
2683851ea85Sgww 				return (-1);
2693851ea85Sgww 			}
2703851ea85Sgww 			*s = strdup(cret.color);
2713851ea85Sgww 			if (callp != &call) {
2723851ea85Sgww 				/* release returned buffer */
2733851ea85Sgww 				(void) munmap((void *)callp, bufsize);
2743851ea85Sgww 			}
2753851ea85Sgww 			if (*s == NULL) {
2763851ea85Sgww 				return (-1);
2773851ea85Sgww 			}
2783851ea85Sgww 			return (0);
2793851ea85Sgww 		} else {
28045916cd2Sjpk 			errno = ENOTSUP;
28145916cd2Sjpk 			*s = NULL;
28245916cd2Sjpk 			return (-1);
28345916cd2Sjpk 		}
28445916cd2Sjpk #undef	ccall
28545916cd2Sjpk #undef	cret
28645916cd2Sjpk 
28745916cd2Sjpk #define	prcall	callp->param.acall.cargs.pr_arg
28845916cd2Sjpk #define	prret	callp->param.aret.rvals.pr_ret
28945916cd2Sjpk 	case PRINTER_TOP_BOTTOM:
29045916cd2Sjpk 		call.callop = PR_TOP;
29145916cd2Sjpk 		break;
29245916cd2Sjpk 	case PRINTER_LABEL:
29345916cd2Sjpk 		call.callop = PR_LABEL;
29445916cd2Sjpk 		break;
29545916cd2Sjpk 	case PRINTER_CAVEATS:
29645916cd2Sjpk 		call.callop = PR_CAVEATS;
2973851ea85Sgww 		string_start = 1;	/* compensate for leading space */
29845916cd2Sjpk 		break;
29945916cd2Sjpk 	case PRINTER_CHANNELS:
30045916cd2Sjpk 		call.callop = PR_CHANNELS;
3013851ea85Sgww 		string_start = 1;	/* compensate for leading space */
30245916cd2Sjpk 		break;
30345916cd2Sjpk 	default:
30445916cd2Sjpk 		errno = EINVAL;
30545916cd2Sjpk 		*s = NULL;
30645916cd2Sjpk 		return (-1);
30745916cd2Sjpk 	}
30845916cd2Sjpk 	/* do the common printer calls */
30945916cd2Sjpk 	datasize = CALL_SIZE(pr_call_t, 0);
31045916cd2Sjpk 	prcall.label = *l;
31145916cd2Sjpk 	prcall.flags = f;
3123851ea85Sgww 	if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
3133851ea85Sgww 		if (callp->reterr != 0) {
3143851ea85Sgww 			errno = EINVAL;
3153851ea85Sgww 			*s = NULL;
3163851ea85Sgww 			return (-1);
3173851ea85Sgww 		}
3183851ea85Sgww 		*s = strdup(&prret.buf[string_start]);
3193851ea85Sgww 		if (callp != &call) {
3203851ea85Sgww 			/* release returned buffer */
3213851ea85Sgww 			(void) munmap((void *)callp, bufsize);
3223851ea85Sgww 		}
3233851ea85Sgww 		if (*s == NULL) {
3243851ea85Sgww 			return (-1);
3253851ea85Sgww 		}
3263851ea85Sgww 		return (0);
3273851ea85Sgww 	} else {
32845916cd2Sjpk 		errno = ENOTSUP;
32945916cd2Sjpk 		*s = NULL;
33045916cd2Sjpk 		return (-1);
33145916cd2Sjpk 	}
33245916cd2Sjpk #undef	prcall
33345916cd2Sjpk #undef	prret
33445916cd2Sjpk }
335*4201a95eSRic Aleshire #endif /* !defined(_KERNEL) */
336