/* * 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 #include #include #include #include #include #include #include #include "clnt.h" #include "labeld.h" #include #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 */