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 2006 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 /* 29 * Binary label to label string translations. 30 */ 31 32 #include <locale.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <strings.h> 37 #include <wchar.h> 38 39 #include <sys/mman.h> 40 41 #include <tsol/label.h> 42 43 #include "clnt.h" 44 #include "labeld.h" 45 #include <sys/tsol/label_macro.h> 46 47 #if !defined(TEXT_DOMAIN) /* should be defined by Makefiles */ 48 #define TEXT_DOMAIN "SYS_TEST" 49 #endif /* TEXT_DOMAIN */ 50 51 static bslabel_t slow; /* static admin_low high sensitivity label */ 52 static bslabel_t shigh; /* static admin_high sensitivity label */ 53 static bclear_t clrlow, clrhigh; /* static admin_low and admin_high Clearance */ 54 55 static char *sstring; /* return string for sb*tos */ 56 static size_t ssize; /* current size of return string */ 57 58 static int 59 return_string(char **string, int str_len, char *val) 60 { 61 char *cpyptr; 62 size_t val_len = strlen(val) + 1; 63 64 if (*string == NULL) { 65 if ((*string = malloc(val_len)) == NULL) 66 return (0); 67 } else if (val_len > str_len) { 68 **string = '\0'; 69 return (0); 70 } 71 72 cpyptr = *string; 73 bcopy(val, cpyptr, val_len); 74 75 return (val_len); 76 } 77 78 void 79 set_label_view(uint_t *callflags, uint_t flags) 80 { 81 if (flags&VIEW_INTERNAL) { 82 *callflags |= LABELS_VIEW_INTERNAL; 83 } else if (flags&VIEW_EXTERNAL) { 84 *callflags |= LABELS_VIEW_EXTERNAL; 85 } 86 } 87 88 int 89 alloc_string(char **string, size_t size, char val) 90 { 91 if (*string == NULL) { 92 if ((*string = malloc(ALLOC_CHUNK)) == NULL) 93 return (0); 94 } else { 95 if ((*string = realloc(*string, size + ALLOC_CHUNK)) == NULL) { 96 **string = val; 97 return (0); 98 } 99 } 100 **string = val; 101 return (ALLOC_CHUNK); 102 } 103 104 #define slcall callp->param.acall.cargs.bsltos_arg 105 #define slret callp->param.aret.rvals.bsltos_ret 106 /* 107 * bsltos - Convert Binary Sensitivity Label to Sensitivity Label string. 108 * 109 * Entry label = Binary Sensitivity Label to be converted. 110 * string = NULL ((char *) 0), if memory to be allocated, 111 * otherwise, pointer to preallocated memory. 112 * str_len = Length of preallocated memory, else ignored. 113 * flags = Logical sum of: 114 * LONG_CLASSIFICATION or SHORT_CLASSIFICATION, 115 * LONG_WORDS or SHORT_WORDS, 116 * VIEW_INTERNAL or VIEW_EXTERNAL, and 117 * NO_CLASSIFICATION. 118 * LONG_CLASSIFICATION, use long classification names. 119 * SHORT_CLASSIFICATION, use short classification 120 * names (default). 121 * NO_CLASSIFICATION, don't translate classification. 122 * LONG_WORDS, use the long form of words (default). 123 * SHORTWORDS, use the short form of words where available. 124 * VIEW_INTERNAL, don't promote/demote admin low/high. 125 * VIEW_EXTERNAL, promote/demote admin low/high. 126 * 127 * Exit string = Sensitivity Label string, or empty string if 128 * not enough preallocated memory. 129 * 130 * Returns -1, If unable to access label encodings database. 131 * 0, If unable to allocate string, 132 * or allocated string to short 133 * (and **string = '\0'). 134 * length (including null) of Sensitivity Label string, 135 * If successful. 136 * 137 * Calls RPC - LABELS_BSLTOS, BCLHIGH, BCLLOW, BCLTOSL, BLEQUAL, 138 * BLTYPE, SETBSLABEL, UCLNT, memcpy, clnt_call, 139 * clnt_perror, malloc, strcat, strlen. 140 * 141 * Uses ADMIN_HIGH, ADMIN_LOW, shigh, slow. 142 */ 143 144 ssize_t 145 bsltos(const bslabel_t *label, char **string, size_t str_len, 146 int flags) 147 { 148 labeld_data_t call; 149 labeld_data_t *callp = &call; 150 size_t bufsize = sizeof (labeld_data_t); 151 size_t datasize = CALL_SIZE(bsltos_call_t, 0); 152 int rval; 153 154 if (!BLTYPE(label, SUN_SL_ID)) { 155 return (-1); 156 } 157 158 call.callop = BSLTOS; 159 slcall.label = *label; 160 slcall.flags = (flags&NO_CLASSIFICATION) ? LABELS_NO_CLASS : 0; 161 slcall.flags |= (flags&SHORT_CLASSIFICATION || 162 !(flags&LONG_CLASSIFICATION)) ? LABELS_SHORT_CLASS : 0; 163 slcall.flags |= (flags&SHORT_WORDS && !(flags&LONG_WORDS)) ? 164 LABELS_SHORT_WORDS : 0; 165 set_label_view(&slcall.flags, flags); 166 167 if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) { 168 169 if (callp->reterr != 0) 170 return (-1); 171 172 /* unpack Sensitivity Label */ 173 174 rval = return_string(string, str_len, slret.slabel); 175 176 if (callp != &call) 177 (void) munmap((void *)callp, bufsize); 178 return (rval); 179 } else if (rval == NOSERVER) { 180 /* server not present */ 181 /* special case admin_high and admin_low */ 182 183 if (!BLTYPE(&slow, SUN_SL_ID)) { 184 /* initialize static labels */ 185 186 BSLLOW(&slow); 187 BSLHIGH(&shigh); 188 } 189 190 if (BLEQUAL(label, &slow)) { 191 return (return_string(string, str_len, ADMIN_LOW)); 192 } else if (BLEQUAL(label, &shigh)) { 193 return (return_string(string, str_len, ADMIN_HIGH)); 194 } 195 } 196 return (-1); 197 } /* bsltos */ 198 #undef slcall 199 #undef slret 200 201 #define clrcall callp->param.acall.cargs.bcleartos_arg 202 #define clrret callp->param.aret.rvals.bcleartos_ret 203 /* 204 * bcleartos - Convert Binary Clearance to Clearance string. 205 * 206 * Entry clearance = Binary Clearance to be converted. 207 * string = NULL ((char *) 0), if memory to be allocated, 208 * otherwise, pointer to preallocated memory. 209 * str_len = Length of preallocated memory, else ignored. 210 * flags = Logical sum of: 211 * LONG_CLASSIFICATION or SHORT_CLASSIFICATION, 212 * LONG_WORDS or SHORT_WORDS, 213 * VIEW_INTERNAL or VIEW_EXTERNAL. 214 * LONG_CLASSIFICATION, use long classification names. 215 * SHORT_CLASSIFICATION, use short classification 216 * names (default). 217 * LONG_WORDS, use the long form of words (default). 218 * SHORTWORDS, use the short form of words where available. 219 * VIEW_INTERNAL, don't promote/demote admin low/high. 220 * VIEW_EXTERNAL, promote/demote admin low/high. 221 * 222 * Exit string = Clearance string, or empty string if not 223 * enough preallocated memory. 224 * 225 * Returns -1, If unable to access label encodings database. 226 * 0, If unable to allocate string, 227 * or allocated string to short 228 * (and **string = '\0'). 229 * length (including null) of Clearance string, 230 * If successful. 231 * 232 * Calls RPC - LABELS_BSLTOS, BCLHIGH, BCLLOW, BCLTOSL, BLEQUAL, 233 * BLTYPE, SETBSLABEL, UCLNT, memcpy, clnt_call, 234 * clnt_perror, malloc, strcat, strlen. 235 * 236 * Uses ADMIN_HIGH, ADMIN_LOW, clrhigh, clrlow. 237 */ 238 239 ssize_t 240 bcleartos(const bclear_t *clearance, char **string, size_t str_len, 241 int flags) 242 { 243 labeld_data_t call; 244 labeld_data_t *callp = &call; 245 size_t bufsize = sizeof (labeld_data_t); 246 size_t datasize = CALL_SIZE(bcleartos_call_t, 0); 247 int rval; 248 249 if (!BLTYPE(clearance, SUN_CLR_ID)) { 250 return (-1); 251 } 252 253 call.callop = BCLEARTOS; 254 clrcall.clear = *clearance; 255 clrcall.flags = (flags&SHORT_CLASSIFICATION || 256 !(flags&LONG_CLASSIFICATION)) ? LABELS_SHORT_CLASS : 0; 257 clrcall.flags |= (flags&SHORT_WORDS && !(flags&LONG_WORDS)) ? 258 LABELS_SHORT_WORDS : 0; 259 set_label_view(&clrcall.flags, flags); 260 261 if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) { 262 263 if (callp->reterr != 0) 264 return (-1); 265 266 /* unpack Clearance */ 267 268 rval = return_string(string, str_len, clrret.cslabel); 269 270 if (callp != &call) 271 /* release return buffer */ 272 (void) munmap((void *)callp, bufsize); 273 return (rval); 274 } else if (rval == NOSERVER) { 275 /* server not present */ 276 /* special case admin_high and admin_low */ 277 278 if (!BLTYPE(&clrlow, SUN_CLR_ID)) { 279 /* initialize static labels */ 280 281 BCLEARLOW(&clrlow); 282 BCLEARHIGH(&clrhigh); 283 } 284 if (BLEQUAL(clearance, &clrlow)) { 285 return (return_string(string, str_len, ADMIN_LOW)); 286 } else if (BLEQUAL(clearance, &clrhigh)) { 287 return (return_string(string, str_len, ADMIN_HIGH)); 288 } 289 } 290 return (-1); 291 } /* bcleartos */ 292 #undef clrcall 293 #undef clrret 294 295 /* 296 * sbsltos - Convert Sensitivity Label to canonical clipped form. 297 * 298 * Entry label = Sensitivity Label to be converted. 299 * len = Maximum length of translated string, excluding NULL. 300 * 0, full string. 301 * sstring = address of string to translate into. 302 * ssize = size of memory currently allocated to sstring. 303 * 304 * Exit sstring = Newly translated string. 305 * ssize = Updated if more memory pre-allocated. 306 * 307 * Returns NULL, If error, len too small, unable to translate, or get 308 * memory for string. 309 * Address of string containing converted value. 310 * 311 * Calls alloc_string, bsltos, strcpy. 312 * 313 * Uses ssize, sstring. 314 */ 315 316 char * 317 sbsltos(const bslabel_t *label, size_t len) 318 { 319 ssize_t slen; /* length including NULL */ 320 wchar_t *wstring; 321 int wccount; 322 323 if (ssize == 0) { 324 /* Allocate string memory. */ 325 if ((ssize = alloc_string(&sstring, ssize, 's')) == 0) 326 /* can't get initial memory for string */ 327 return (NULL); 328 } 329 330 again: 331 if ((slen = bsltos(label, &sstring, ssize, 332 (SHORT_CLASSIFICATION | LONG_WORDS))) <= 0) { 333 /* error in translation */ 334 if (slen == 0) { 335 if (*sstring == '\0') { 336 int newsize; 337 /* sstring not long enough */ 338 if ((newsize = alloc_string(&sstring, ssize, 339 's')) == 0) { 340 /* Can't get more memory */ 341 return (NULL); 342 } 343 ssize += newsize; 344 goto again; 345 } 346 } 347 return (NULL); 348 } 349 if (len == 0) { 350 return (sstring); 351 } else if (len < MIN_SL_LEN) { 352 return (NULL); 353 } 354 if ((wstring = malloc(slen * sizeof (wchar_t))) == NULL) 355 return (NULL); 356 if ((wccount = mbstowcs(wstring, sstring, slen - 1)) == -1) { 357 free(wstring); 358 return (NULL); 359 } 360 if (wccount > len) { 361 wchar_t *clipp = wstring + (len - 2); 362 363 /* Adjust string size to desired length */ 364 365 clipp[0] = L'<'; 366 clipp[1] = L'-'; 367 clipp[2] = L'\0'; 368 369 while (wcstombs(NULL, wstring, 0) >= ssize) { 370 int newsize; 371 372 /* sstring not long enough */ 373 if ((newsize = alloc_string(&sstring, ssize, 's')) == 374 0) { 375 /* Can't get more memory */ 376 return (NULL); 377 } 378 ssize += newsize; 379 } 380 381 if ((wccount = wcstombs(sstring, wstring, ssize)) == -1) { 382 free(wstring); 383 return (NULL); 384 } 385 } 386 free(wstring); 387 388 return (sstring); 389 } /* sbsltos */ 390 391 /* 392 * sbcleartos - Convert Clearance to canonical clipped form. 393 * 394 * Entry clearance = Clearance to be converted. 395 * len = Maximum length of translated string, excluding NULL. 396 * 0, full string. 397 * sstring = address of string to translate into. 398 * ssize = size of memory currently allocated to sstring. 399 * 400 * Exit sstring = Newly translated string. 401 * ssize = Updated if more memory pre-allocated. 402 * 403 * Returns NULL, If error, len too small, unable to translate, or get 404 * memory for string. 405 * Address of string containing converted value. 406 * 407 * Calls alloc_string, bcleartos, strcpy. 408 * 409 * Uses ssize, sstring. 410 */ 411 412 char * 413 sbcleartos(const bclear_t *clearance, size_t len) 414 { 415 ssize_t slen; /* length including NULL */ 416 wchar_t *wstring; 417 int wccount; 418 419 if (ssize == 0) { 420 /* Allocate string memory. */ 421 if ((ssize = alloc_string(&sstring, ssize, 'c')) == 0) 422 /* can't get initial memory for string */ 423 return (NULL); 424 } 425 426 again: 427 if ((slen = bcleartos(clearance, &sstring, ssize, 428 (SHORT_CLASSIFICATION | LONG_WORDS))) <= 0) { 429 /* error in translation */ 430 if (slen == 0) { 431 if (*sstring == '\0') { 432 int newsize; 433 /* sstring not long enough */ 434 if ((newsize = alloc_string(&sstring, ssize, 435 'c')) == 0) { 436 /* Can't get more memory */ 437 return (NULL); 438 } 439 ssize += newsize; 440 goto again; 441 } 442 } 443 return (NULL); 444 } 445 if (len == 0) { 446 return (sstring); 447 } else if (len < MIN_CLR_LEN) { 448 return (NULL); 449 } 450 if ((wstring = malloc(slen * sizeof (wchar_t))) == NULL) 451 return (NULL); 452 if ((wccount = mbstowcs(wstring, sstring, slen - 1)) == -1) { 453 free(wstring); 454 return (NULL); 455 } 456 if (wccount > len) { 457 wchar_t *clipp = wstring + (len - 2); 458 459 /* Adjust string size to desired length */ 460 461 clipp[0] = L'<'; 462 clipp[1] = L'-'; 463 clipp[2] = L'\0'; 464 465 while (wcstombs(NULL, wstring, 0) >= ssize) { 466 int newsize; 467 468 /* sstring not long enough */ 469 if ((newsize = alloc_string(&sstring, ssize, 'c')) == 470 0) { 471 /* Can't get more memory */ 472 free(wstring); 473 return (NULL); 474 } 475 ssize += newsize; 476 } 477 if ((wccount = wcstombs(sstring, wstring, ssize)) == -1) { 478 free(wstring); 479 return (NULL); 480 } 481 } 482 free(wstring); 483 484 return (sstring); 485 } /* sbcleartos */ 486