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