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