| /* |
| * CDDL HEADER START |
| * |
| * The contents of this file are subject to the terms of the |
| * Common Development and Distribution License (the "License"). |
| * You may not use this file except in compliance with the License. |
| * |
| * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
| * or http://www.opensolaris.org/os/licensing. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * |
| * When distributing Covered Code, include this CDDL HEADER in each |
| * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
| * If applicable, add the following below this CDDL HEADER, with the |
| * fields enclosed by brackets "[]" replaced with your own identifying |
| * information: Portions Copyright [yyyy] [name of copyright owner] |
| * |
| * CDDL HEADER END |
| */ |
| /* |
| * Copyright 2006 Sun Microsystems, Inc. All rights reserved. |
| * Use is subject to license terms. |
| */ |
| |
| #pragma ident "%Z%%M% %I% %E% SMI" |
| |
| /* |
| * Binary label to label string translations. |
| */ |
| |
| #include <locale.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <strings.h> |
| #include <wchar.h> |
| |
| #include <sys/mman.h> |
| |
| #include <tsol/label.h> |
| |
| #include "clnt.h" |
| #include "labeld.h" |
| #include <sys/tsol/label_macro.h> |
| |
| #if !defined(TEXT_DOMAIN) /* should be defined by Makefiles */ |
| #define TEXT_DOMAIN "SYS_TEST" |
| #endif /* TEXT_DOMAIN */ |
| |
| static bslabel_t slow; /* static admin_low high sensitivity label */ |
| static bslabel_t shigh; /* static admin_high sensitivity label */ |
| static bclear_t clrlow, clrhigh; /* static admin_low and admin_high Clearance */ |
| |
| static char *sstring; /* return string for sb*tos */ |
| static size_t ssize; /* current size of return string */ |
| |
| static int |
| return_string(char **string, int str_len, char *val) |
| { |
| char *cpyptr; |
| size_t val_len = strlen(val) + 1; |
| |
| if (*string == NULL) { |
| if ((*string = malloc(val_len)) == NULL) |
| return (0); |
| } else if (val_len > str_len) { |
| **string = '\0'; |
| return (0); |
| } |
| |
| cpyptr = *string; |
| bcopy(val, cpyptr, val_len); |
| |
| return (val_len); |
| } |
| |
| void |
| set_label_view(uint_t *callflags, uint_t flags) |
| { |
| if (flags&VIEW_INTERNAL) { |
| *callflags |= LABELS_VIEW_INTERNAL; |
| } else if (flags&VIEW_EXTERNAL) { |
| *callflags |= LABELS_VIEW_EXTERNAL; |
| } |
| } |
| |
| int |
| alloc_string(char **string, size_t size, char val) |
| { |
| if (*string == NULL) { |
| if ((*string = malloc(ALLOC_CHUNK)) == NULL) |
| return (0); |
| } else { |
| if ((*string = realloc(*string, size + ALLOC_CHUNK)) == NULL) { |
| **string = val; |
| return (0); |
| } |
| } |
| **string = val; |
| return (ALLOC_CHUNK); |
| } |
| |
| #define slcall callp->param.acall.cargs.bsltos_arg |
| #define slret callp->param.aret.rvals.bsltos_ret |
| /* |
| * bsltos - Convert Binary Sensitivity Label to Sensitivity Label string. |
| * |
| * Entry label = Binary Sensitivity Label to be converted. |
| * string = NULL ((char *) 0), if memory to be allocated, |
| * otherwise, pointer to preallocated memory. |
| * str_len = Length of preallocated memory, else ignored. |
| * flags = Logical sum of: |
| * LONG_CLASSIFICATION or SHORT_CLASSIFICATION, |
| * LONG_WORDS or SHORT_WORDS, |
| * VIEW_INTERNAL or VIEW_EXTERNAL, and |
| * NO_CLASSIFICATION. |
| * LONG_CLASSIFICATION, use long classification names. |
| * SHORT_CLASSIFICATION, use short classification |
| * names (default). |
| * NO_CLASSIFICATION, don't translate classification. |
| * LONG_WORDS, use the long form of words (default). |
| * SHORTWORDS, use the short form of words where available. |
| * VIEW_INTERNAL, don't promote/demote admin low/high. |
| * VIEW_EXTERNAL, promote/demote admin low/high. |
| * |
| * Exit string = Sensitivity Label string, or empty string if |
| * not enough preallocated memory. |
| * |
| * Returns -1, If unable to access label encodings database. |
| * 0, If unable to allocate string, |
| * or allocated string to short |
| * (and **string = '\0'). |
| * length (including null) of Sensitivity Label string, |
| * If successful. |
| * |
| * Calls RPC - LABELS_BSLTOS, BCLHIGH, BCLLOW, BCLTOSL, BLEQUAL, |
| * BLTYPE, SETBSLABEL, UCLNT, memcpy, clnt_call, |
| * clnt_perror, malloc, strcat, strlen. |
| * |
| * Uses ADMIN_HIGH, ADMIN_LOW, shigh, slow. |
| */ |
| |
| ssize_t |
| bsltos(const bslabel_t *label, char **string, size_t str_len, |
| int flags) |
| { |
| labeld_data_t call; |
| labeld_data_t *callp = &call; |
| size_t bufsize = sizeof (labeld_data_t); |
| size_t datasize = CALL_SIZE(bsltos_call_t, 0); |
| int rval; |
| |
| if (!BLTYPE(label, SUN_SL_ID)) { |
| return (-1); |
| } |
| |
| call.callop = BSLTOS; |
| slcall.label = *label; |
| slcall.flags = (flags&NO_CLASSIFICATION) ? LABELS_NO_CLASS : 0; |
| slcall.flags |= (flags&SHORT_CLASSIFICATION || |
| !(flags&LONG_CLASSIFICATION)) ? LABELS_SHORT_CLASS : 0; |
| slcall.flags |= (flags&SHORT_WORDS && !(flags&LONG_WORDS)) ? |
| LABELS_SHORT_WORDS : 0; |
| set_label_view(&slcall.flags, flags); |
| |
| if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) { |
| |
| if (callp->reterr != 0) |
| return (-1); |
| |
| /* unpack Sensitivity Label */ |
| |
| rval = return_string(string, str_len, slret.slabel); |
| |
| if (callp != &call) |
| (void) munmap((void *)callp, bufsize); |
| return (rval); |
| } else if (rval == NOSERVER) { |
| /* server not present */ |
| /* special case admin_high and admin_low */ |
| |
| if (!BLTYPE(&slow, SUN_SL_ID)) { |
| /* initialize static labels */ |
| |
| BSLLOW(&slow); |
| BSLHIGH(&shigh); |
| } |
| |
| if (BLEQUAL(label, &slow)) { |
| return (return_string(string, str_len, ADMIN_LOW)); |
| } else if (BLEQUAL(label, &shigh)) { |
| return (return_string(string, str_len, ADMIN_HIGH)); |
| } |
| } |
| return (-1); |
| } /* bsltos */ |
| #undef slcall |
| #undef slret |
| |
| #define clrcall callp->param.acall.cargs.bcleartos_arg |
| #define clrret callp->param.aret.rvals.bcleartos_ret |
| /* |
| * bcleartos - Convert Binary Clearance to Clearance string. |
| * |
| * Entry clearance = Binary Clearance to be converted. |
| * string = NULL ((char *) 0), if memory to be allocated, |
| * otherwise, pointer to preallocated memory. |
| * str_len = Length of preallocated memory, else ignored. |
| * flags = Logical sum of: |
| * LONG_CLASSIFICATION or SHORT_CLASSIFICATION, |
| * LONG_WORDS or SHORT_WORDS, |
| * VIEW_INTERNAL or VIEW_EXTERNAL. |
| * LONG_CLASSIFICATION, use long classification names. |
| * SHORT_CLASSIFICATION, use short classification |
| * names (default). |
| * LONG_WORDS, use the long form of words (default). |
| * SHORTWORDS, use the short form of words where available. |
| * VIEW_INTERNAL, don't promote/demote admin low/high. |
| * VIEW_EXTERNAL, promote/demote admin low/high. |
| * |
| * Exit string = Clearance string, or empty string if not |
| * enough preallocated memory. |
| * |
| * Returns -1, If unable to access label encodings database. |
| * 0, If unable to allocate string, |
| * or allocated string to short |
| * (and **string = '\0'). |
| * length (including null) of Clearance string, |
| * If successful. |
| * |
| * Calls RPC - LABELS_BSLTOS, BCLHIGH, BCLLOW, BCLTOSL, BLEQUAL, |
| * BLTYPE, SETBSLABEL, UCLNT, memcpy, clnt_call, |
| * clnt_perror, malloc, strcat, strlen. |
| * |
| * Uses ADMIN_HIGH, ADMIN_LOW, clrhigh, clrlow. |
| */ |
| |
| ssize_t |
| bcleartos(const bclear_t *clearance, char **string, size_t str_len, |
| int flags) |
| { |
| labeld_data_t call; |
| labeld_data_t *callp = &call; |
| size_t bufsize = sizeof (labeld_data_t); |
| size_t datasize = CALL_SIZE(bcleartos_call_t, 0); |
| int rval; |
| |
| if (!BLTYPE(clearance, SUN_CLR_ID)) { |
| return (-1); |
| } |
| |
| call.callop = BCLEARTOS; |
| clrcall.clear = *clearance; |
| clrcall.flags = (flags&SHORT_CLASSIFICATION || |
| !(flags&LONG_CLASSIFICATION)) ? LABELS_SHORT_CLASS : 0; |
| clrcall.flags |= (flags&SHORT_WORDS && !(flags&LONG_WORDS)) ? |
| LABELS_SHORT_WORDS : 0; |
| set_label_view(&clrcall.flags, flags); |
| |
| if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) { |
| |
| if (callp->reterr != 0) |
| return (-1); |
| |
| /* unpack Clearance */ |
| |
| rval = return_string(string, str_len, clrret.cslabel); |
| |
| if (callp != &call) |
| /* release return buffer */ |
| (void) munmap((void *)callp, bufsize); |
| return (rval); |
| } else if (rval == NOSERVER) { |
| /* server not present */ |
| /* special case admin_high and admin_low */ |
| |
| if (!BLTYPE(&clrlow, SUN_CLR_ID)) { |
| /* initialize static labels */ |
| |
| BCLEARLOW(&clrlow); |
| BCLEARHIGH(&clrhigh); |
| } |
| if (BLEQUAL(clearance, &clrlow)) { |
| return (return_string(string, str_len, ADMIN_LOW)); |
| } else if (BLEQUAL(clearance, &clrhigh)) { |
| return (return_string(string, str_len, ADMIN_HIGH)); |
| } |
| } |
| return (-1); |
| } /* bcleartos */ |
| #undef clrcall |
| #undef clrret |
| |
| /* |
| * sbsltos - Convert Sensitivity Label to canonical clipped form. |
| * |
| * Entry label = Sensitivity Label to be converted. |
| * len = Maximum length of translated string, excluding NULL. |
| * 0, full string. |
| * sstring = address of string to translate into. |
| * ssize = size of memory currently allocated to sstring. |
| * |
| * Exit sstring = Newly translated string. |
| * ssize = Updated if more memory pre-allocated. |
| * |
| * Returns NULL, If error, len too small, unable to translate, or get |
| * memory for string. |
| * Address of string containing converted value. |
| * |
| * Calls alloc_string, bsltos, strcpy. |
| * |
| * Uses ssize, sstring. |
| */ |
| |
| char * |
| sbsltos(const bslabel_t *label, size_t len) |
| { |
| ssize_t slen; /* length including NULL */ |
| wchar_t *wstring; |
| int wccount; |
| |
| if (ssize == 0) { |
| /* Allocate string memory. */ |
| if ((ssize = alloc_string(&sstring, ssize, 's')) == 0) |
| /* can't get initial memory for string */ |
| return (NULL); |
| } |
| |
| again: |
| if ((slen = bsltos(label, &sstring, ssize, |
| (SHORT_CLASSIFICATION | LONG_WORDS))) <= 0) { |
| /* error in translation */ |
| if (slen == 0) { |
| if (*sstring == '\0') { |
| int newsize; |
| /* sstring not long enough */ |
| if ((newsize = alloc_string(&sstring, ssize, |
| 's')) == 0) { |
| /* Can't get more memory */ |
| return (NULL); |
| } |
| ssize += newsize; |
| goto again; |
| } |
| } |
| return (NULL); |
| } |
| if (len == 0) { |
| return (sstring); |
| } else if (len < MIN_SL_LEN) { |
| return (NULL); |
| } |
| if ((wstring = malloc(slen * sizeof (wchar_t))) == NULL) |
| return (NULL); |
| if ((wccount = mbstowcs(wstring, sstring, slen - 1)) == -1) { |
| free(wstring); |
| return (NULL); |
| } |
| if (wccount > len) { |
| wchar_t *clipp = wstring + (len - 2); |
| |
| /* Adjust string size to desired length */ |
| |
| clipp[0] = L'<'; |
| clipp[1] = L'-'; |
| clipp[2] = L'\0'; |
| |
| while (wcstombs(NULL, wstring, 0) >= ssize) { |
| int newsize; |
| |
| /* sstring not long enough */ |
| if ((newsize = alloc_string(&sstring, ssize, 's')) == |
| 0) { |
| /* Can't get more memory */ |
| return (NULL); |
| } |
| ssize += newsize; |
| } |
| |
| if ((wccount = wcstombs(sstring, wstring, ssize)) == -1) { |
| free(wstring); |
| return (NULL); |
| } |
| } |
| free(wstring); |
| |
| return (sstring); |
| } /* sbsltos */ |
| |
| /* |
| * sbcleartos - Convert Clearance to canonical clipped form. |
| * |
| * Entry clearance = Clearance to be converted. |
| * len = Maximum length of translated string, excluding NULL. |
| * 0, full string. |
| * sstring = address of string to translate into. |
| * ssize = size of memory currently allocated to sstring. |
| * |
| * Exit sstring = Newly translated string. |
| * ssize = Updated if more memory pre-allocated. |
| * |
| * Returns NULL, If error, len too small, unable to translate, or get |
| * memory for string. |
| * Address of string containing converted value. |
| * |
| * Calls alloc_string, bcleartos, strcpy. |
| * |
| * Uses ssize, sstring. |
| */ |
| |
| char * |
| sbcleartos(const bclear_t *clearance, size_t len) |
| { |
| ssize_t slen; /* length including NULL */ |
| wchar_t *wstring; |
| int wccount; |
| |
| if (ssize == 0) { |
| /* Allocate string memory. */ |
| if ((ssize = alloc_string(&sstring, ssize, 'c')) == 0) |
| /* can't get initial memory for string */ |
| return (NULL); |
| } |
| |
| again: |
| if ((slen = bcleartos(clearance, &sstring, ssize, |
| (SHORT_CLASSIFICATION | LONG_WORDS))) <= 0) { |
| /* error in translation */ |
| if (slen == 0) { |
| if (*sstring == '\0') { |
| int newsize; |
| /* sstring not long enough */ |
| if ((newsize = alloc_string(&sstring, ssize, |
| 'c')) == 0) { |
| /* Can't get more memory */ |
| return (NULL); |
| } |
| ssize += newsize; |
| goto again; |
| } |
| } |
| return (NULL); |
| } |
| if (len == 0) { |
| return (sstring); |
| } else if (len < MIN_CLR_LEN) { |
| return (NULL); |
| } |
| if ((wstring = malloc(slen * sizeof (wchar_t))) == NULL) |
| return (NULL); |
| if ((wccount = mbstowcs(wstring, sstring, slen - 1)) == -1) { |
| free(wstring); |
| return (NULL); |
| } |
| if (wccount > len) { |
| wchar_t *clipp = wstring + (len - 2); |
| |
| /* Adjust string size to desired length */ |
| |
| clipp[0] = L'<'; |
| clipp[1] = L'-'; |
| clipp[2] = L'\0'; |
| |
| while (wcstombs(NULL, wstring, 0) >= ssize) { |
| int newsize; |
| |
| /* sstring not long enough */ |
| if ((newsize = alloc_string(&sstring, ssize, 'c')) == |
| 0) { |
| /* Can't get more memory */ |
| free(wstring); |
| return (NULL); |
| } |
| ssize += newsize; |
| } |
| if ((wccount = wcstombs(sstring, wstring, ssize)) == -1) { |
| free(wstring); |
| return (NULL); |
| } |
| } |
| free(wstring); |
| |
| return (sstring); |
| } /* sbcleartos */ |