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 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 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 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