Home | History | Annotate | Download | only in common
      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