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