xref: /illumos-gate/usr/src/lib/libtsol/common/stob.c (revision 1da57d55)
145916cd2Sjpk /*
245916cd2Sjpk  * CDDL HEADER START
345916cd2Sjpk  *
445916cd2Sjpk  * The contents of this file are subject to the terms of the
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * You may not use this file except in compliance with the License.
745916cd2Sjpk  *
845916cd2Sjpk  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
945916cd2Sjpk  * or http://www.opensolaris.org/os/licensing.
1045916cd2Sjpk  * See the License for the specific language governing permissions
1145916cd2Sjpk  * and limitations under the License.
1245916cd2Sjpk  *
1345916cd2Sjpk  * When distributing Covered Code, include this CDDL HEADER in each
1445916cd2Sjpk  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1545916cd2Sjpk  * If applicable, add the following below this CDDL HEADER, with the
1645916cd2Sjpk  * fields enclosed by brackets "[]" replaced with your own identifying
1745916cd2Sjpk  * information: Portions Copyright [yyyy] [name of copyright owner]
1845916cd2Sjpk  *
1945916cd2Sjpk  * CDDL HEADER END
2045916cd2Sjpk  */
2145916cd2Sjpk /*
22*a6080eb5Sgww  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2345916cd2Sjpk  * Use is subject to license terms.
2445916cd2Sjpk  */
2545916cd2Sjpk 
2645916cd2Sjpk /*
2745916cd2Sjpk  *	String to binary label translations.
2845916cd2Sjpk  */
2945916cd2Sjpk 
3045916cd2Sjpk #include <ctype.h>
3145916cd2Sjpk #include <locale.h>
3245916cd2Sjpk #include <stdio.h>
3345916cd2Sjpk #include <stdlib.h>
3445916cd2Sjpk #include <strings.h>
3545916cd2Sjpk 
3645916cd2Sjpk #include <tsol/label.h>
3745916cd2Sjpk 
3845916cd2Sjpk #include "labeld.h"
3945916cd2Sjpk #include <sys/tsol/label_macro.h>
4045916cd2Sjpk 
4145916cd2Sjpk #undef	CALL_SIZE
4245916cd2Sjpk #define	CALL_SIZE(type, buf)	(size_t)(sizeof (type) - BUFSIZE + sizeof (int)\
4345916cd2Sjpk 	+ (buf))
4445916cd2Sjpk 
4545916cd2Sjpk #if	!defined(TEXT_DOMAIN)		/* should be defined by Makefiles */
4645916cd2Sjpk #define	TEXT_DOMAIN "SYS_TEST"
4745916cd2Sjpk #endif	/* TEXT_DOMAIN */
4845916cd2Sjpk 
4945916cd2Sjpk /* short hands */
5045916cd2Sjpk 
5145916cd2Sjpk #define	IS_ADMIN_LOW(sl) \
5245916cd2Sjpk 	((strncasecmp(sl, ADMIN_LOW, (sizeof (ADMIN_LOW) - 1)) == 0))
5345916cd2Sjpk 
5445916cd2Sjpk #define	IS_ADMIN_HIGH(sh) \
5545916cd2Sjpk 	((strncasecmp(sh, ADMIN_HIGH, (sizeof (ADMIN_HIGH) - 1)) == 0))
5645916cd2Sjpk 
5745916cd2Sjpk #define	ISHEX(f, s) \
5845916cd2Sjpk 	(((((f) & NEW_LABEL) == ((f) | NEW_LABEL)) || \
5945916cd2Sjpk 	(((f) & NO_CORRECTION) == ((f) | NO_CORRECTION))) && \
6045916cd2Sjpk 	(((s)[0] == '0') && (((s)[1] == 'x') || ((s)[1] == 'X'))))
6145916cd2Sjpk 
6245916cd2Sjpk #define	slcall callp->param.acall.cargs.stobsl_arg
6345916cd2Sjpk #define	slret callp->param.aret.rvals.stobsl_ret
6445916cd2Sjpk /*
6545916cd2Sjpk  *	stobsl - Translate Sensitivity Label string to a Binary Sensitivity
6645916cd2Sjpk  *		Label.
6745916cd2Sjpk  *
6845916cd2Sjpk  *	Entry	string = Sensitivity Label string to be translated.
6945916cd2Sjpk  *		label = Address of Binary Sensitivity Label to be initialized or
7045916cd2Sjpk  *			updated.
7145916cd2Sjpk  *		flags = Flags to control translation:
7245916cd2Sjpk  *			NO_CORRECTION implies NEW_LABEL.
7345916cd2Sjpk  *			NEW_LABEL, Initialize the label to a valid empty
7445916cd2Sjpk  *				Sensitivity Label structure.
7545916cd2Sjpk  *			NO_CORRECTION, Initialize the label to a valid
7645916cd2Sjpk  *				empty Sensitivity Label structure.
7745916cd2Sjpk  *				Prohibit correction to the Sensitivity Label.
7845916cd2Sjpk  *			Other, pass existing Sensitivity Label through for
7945916cd2Sjpk  *				modification.
8045916cd2Sjpk  *
8145916cd2Sjpk  *	Exit	label = Translated (updated) Binary Sensitivity Label.
8245916cd2Sjpk  *		error = If error reported, the error indicator,
8345916cd2Sjpk  *				-1, Unable to access label encodings file;
8445916cd2Sjpk  *				 0, Invalid binary label passed;
8545916cd2Sjpk  *				>0, Position after the first character in
8645916cd2Sjpk  *				    string of error, 1 indicates entire string.
8745916cd2Sjpk  *			Otherwise, unchanged.
8845916cd2Sjpk  *
8945916cd2Sjpk  *	Returns	0, If error.
9045916cd2Sjpk  *		1, If successful.
9145916cd2Sjpk  *
9245916cd2Sjpk  *	Calls	__call_labeld(STOBSL), ISHEX, htobsl, strlen,
9345916cd2Sjpk  *			isspace,
9445916cd2Sjpk  *			strncasecmp.
9545916cd2Sjpk  *
9645916cd2Sjpk  *	Uses	ADMIN_HIGH, ADMIN_LOW.
9745916cd2Sjpk  */
9845916cd2Sjpk 
9945916cd2Sjpk int
stobsl(const char * string,bslabel_t * label,int flags,int * error)10045916cd2Sjpk stobsl(const char *string, bslabel_t *label, int flags, int *error)
10145916cd2Sjpk {
10245916cd2Sjpk 	labeld_data_t	call;
10345916cd2Sjpk 	labeld_data_t	*callp = &call;
10445916cd2Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
10545916cd2Sjpk 	size_t	datasize = CALL_SIZE(stobsl_call_t, strlen(string) + 1);
10645916cd2Sjpk 	int	rval;
10745916cd2Sjpk 	char	*s = (char *)string;
10845916cd2Sjpk 
10945916cd2Sjpk 	while (isspace(*s))
11045916cd2Sjpk 		s++;
11145916cd2Sjpk 	/* accept a leading '[' */
11245916cd2Sjpk 	if (*s == '[') {
11345916cd2Sjpk 		s++;
11445916cd2Sjpk 		while (isspace(*s))
11545916cd2Sjpk 			s++;
11645916cd2Sjpk 	}
11745916cd2Sjpk 	if (ISHEX(flags, s)) {
11845916cd2Sjpk 		if (htobsl(s, label)) {
11945916cd2Sjpk 			return (1);
12045916cd2Sjpk 		} else {
12145916cd2Sjpk 			if (error != NULL)
12245916cd2Sjpk 				*error = 1;
12345916cd2Sjpk 			return (0);
12445916cd2Sjpk 		}
12545916cd2Sjpk 	}
12645916cd2Sjpk 
12745916cd2Sjpk 	if (datasize > bufsize) {
12845916cd2Sjpk 		if ((callp = malloc(datasize)) == NULL) {
12945916cd2Sjpk 			if (error != NULL)
13045916cd2Sjpk 				*error = -1;
13145916cd2Sjpk 			return (0);
13245916cd2Sjpk 		}
13345916cd2Sjpk 		bufsize = datasize;
13445916cd2Sjpk 	}
13545916cd2Sjpk 	callp->callop = STOBSL;
13645916cd2Sjpk 	slcall.flags  = (flags&NEW_LABEL) ? LABELS_NEW_LABEL : 0;
13745916cd2Sjpk 	slcall.flags |= (flags&NO_CORRECTION) ? LABELS_FULL_PARSE : 0;
13845916cd2Sjpk 	slcall.label = *label;
13945916cd2Sjpk 	(void) strcpy(slcall.string, string);
14045916cd2Sjpk 
14145916cd2Sjpk 	if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) {
14245916cd2Sjpk 		int err = callp->reterr;
14345916cd2Sjpk 
14445916cd2Sjpk 		if (callp != &call) {
14545916cd2Sjpk 			/* free allocated buffer */
14645916cd2Sjpk 			free(callp);
14745916cd2Sjpk 		}
14845916cd2Sjpk 		/*
14945916cd2Sjpk 		 * reterr == 0, OK,
15045916cd2Sjpk 		 * reterr < 0, invalid binary label,
15145916cd2Sjpk 		 * reterr > 0 error position, 1 == whole string
15245916cd2Sjpk 		 */
15345916cd2Sjpk 		if (err == 0) {
15445916cd2Sjpk 			*label = slret.label;
15545916cd2Sjpk 			return (1);
15645916cd2Sjpk 		} else if (err < 0) {
15745916cd2Sjpk 			err = 0;
15845916cd2Sjpk 		}
15945916cd2Sjpk 		if (error != NULL)
16045916cd2Sjpk 			*error = err;
16145916cd2Sjpk 		return (0);
16245916cd2Sjpk 	} else if (rval == NOSERVER) {
16345916cd2Sjpk 		if (callp != &call) {
16445916cd2Sjpk 			/* free allocated buffer */
16545916cd2Sjpk 			free(callp);
16645916cd2Sjpk 		}
16745916cd2Sjpk 		/* server not present */
16845916cd2Sjpk 		/* special case Admin High and Admin Low */
16945916cd2Sjpk 		if (IS_ADMIN_LOW(s)) {
17045916cd2Sjpk 			BSLLOW(label);
17145916cd2Sjpk 		} else if (IS_ADMIN_HIGH(s)) {
17245916cd2Sjpk 			BSLHIGH(label);
17345916cd2Sjpk 		} else {
17445916cd2Sjpk 			goto err1;
17545916cd2Sjpk 		}
17645916cd2Sjpk 		return (1);
17745916cd2Sjpk 	}
17845916cd2Sjpk 	if (callp != &call) {
17945916cd2Sjpk 		/* free allocated buffer */
18045916cd2Sjpk 		free(callp);
18145916cd2Sjpk 	}
18245916cd2Sjpk err1:
18345916cd2Sjpk 	if (error != NULL)
18445916cd2Sjpk 		*error = -1;
18545916cd2Sjpk 	return (0);
18645916cd2Sjpk }  /* stobsl */
18745916cd2Sjpk #undef	slcall
18845916cd2Sjpk #undef	slret
18945916cd2Sjpk 
19045916cd2Sjpk #define	clrcall callp->param.acall.cargs.stobclear_arg
19145916cd2Sjpk #define	clrret callp->param.aret.rvals.stobclear_ret
19245916cd2Sjpk /*
19345916cd2Sjpk  *	stobclear - Translate Clearance string to a Binary Clearance.
19445916cd2Sjpk  *
19545916cd2Sjpk  *	Entry	string = Clearance string to be translated.
19645916cd2Sjpk  *		clearance = Address of Binary Clearance to be initialized or
19745916cd2Sjpk  *			updated.
19845916cd2Sjpk  *		flags = Flags to control translation:
19945916cd2Sjpk  *			NO_CORRECTION implies NEW_LABEL.
20045916cd2Sjpk  *			NEW_LABEL, Initialize the label to a valid empty
20145916cd2Sjpk  *				Sensitivity Label structure.
20245916cd2Sjpk  *			NO_CORRECTION, Initialize the label to a valid
20345916cd2Sjpk  *				empty Sensitivity Label structure.
20445916cd2Sjpk  *				Prohibit correction to the Sensitivity Label.
20545916cd2Sjpk  *			Other, pass existing Sensitivity Label through for
20645916cd2Sjpk  *				modification.
20745916cd2Sjpk  *
20845916cd2Sjpk  *	Exit	clearance = Translated (updated) Binary Clearance.
20945916cd2Sjpk  *		error = If error reported, the error indicator,
21045916cd2Sjpk  *				-1, Unable to access label encodings file;
21145916cd2Sjpk  *				 0, Invalid binary label passed;
21245916cd2Sjpk  *				>0, Position after the first character in
21345916cd2Sjpk  *				    string of error, 1 indicates entire string.
21445916cd2Sjpk  *			Otherwise, unchanged.
21545916cd2Sjpk  *
21645916cd2Sjpk  *	Returns	0, If error.
21745916cd2Sjpk  *		1, If successful.
21845916cd2Sjpk  *
21945916cd2Sjpk  *	Calls	__call_labeld(STOBCLEAR), ISHEX, htobsl, strlen,
22045916cd2Sjpk  *			isspace,
22145916cd2Sjpk  *			strncasecmp.
22245916cd2Sjpk  *
22345916cd2Sjpk  *	Uses	ADMIN_HIGH, ADMIN_LOW.
22445916cd2Sjpk  */
22545916cd2Sjpk 
22645916cd2Sjpk int
stobclear(const char * string,bclear_t * clearance,int flags,int * error)22745916cd2Sjpk stobclear(const char *string, bclear_t *clearance, int flags, int *error)
22845916cd2Sjpk {
22945916cd2Sjpk 	labeld_data_t	call;
23045916cd2Sjpk 	labeld_data_t	*callp = &call;
23145916cd2Sjpk 	size_t	bufsize = sizeof (labeld_data_t);
232*a6080eb5Sgww 	size_t	datasize = CALL_SIZE(stobclear_call_t, strlen(string) + 1);
23345916cd2Sjpk 	int	rval;
23445916cd2Sjpk 
23545916cd2Sjpk 	if (ISHEX(flags, string)) {
23645916cd2Sjpk 		if (htobclear(string, clearance)) {
23745916cd2Sjpk 			return (1);
23845916cd2Sjpk 		} else {
23945916cd2Sjpk 			if (error != NULL)
24045916cd2Sjpk 				*error = 1;
24145916cd2Sjpk 			return (0);
24245916cd2Sjpk 		}
24345916cd2Sjpk 	}
24445916cd2Sjpk 
24545916cd2Sjpk 	if (datasize > bufsize) {
24645916cd2Sjpk 		if ((callp = malloc(datasize)) == NULL) {
24745916cd2Sjpk 			if (error != NULL)
24845916cd2Sjpk 				*error = -1;
24945916cd2Sjpk 			return (0);
25045916cd2Sjpk 		}
25145916cd2Sjpk 		bufsize = datasize;
25245916cd2Sjpk 	}
25345916cd2Sjpk 	callp->callop = STOBCLEAR;
25445916cd2Sjpk 	clrcall.flags  = (flags&NEW_LABEL) ? LABELS_NEW_LABEL : 0;
25545916cd2Sjpk 	clrcall.flags |= (flags&NO_CORRECTION) ? LABELS_FULL_PARSE : 0;
25645916cd2Sjpk 	clrcall.clear = *clearance;
25745916cd2Sjpk 	(void) strcpy(clrcall.string, string);
25845916cd2Sjpk 
25945916cd2Sjpk 	if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) {
26045916cd2Sjpk 		int err = callp->reterr;
26145916cd2Sjpk 
26245916cd2Sjpk 		if (callp != &call) {
26345916cd2Sjpk 			/* free allocated buffer */
26445916cd2Sjpk 			free(callp);
26545916cd2Sjpk 		}
26645916cd2Sjpk 		/*
26745916cd2Sjpk 		 * reterr == 0, OK,
26845916cd2Sjpk 		 * reterr < 0, invalid binary label,
26945916cd2Sjpk 		 * reterr > 0 error position, 1 == whole string
27045916cd2Sjpk 		 */
27145916cd2Sjpk 		if (err == 0) {
27245916cd2Sjpk 			*clearance = clrret.clear;
27345916cd2Sjpk 			return (1);
27445916cd2Sjpk 		} else if (err < 0) {
27545916cd2Sjpk 			err = 0;
27645916cd2Sjpk 		}
27745916cd2Sjpk 		if (error != NULL)
27845916cd2Sjpk 			*error = err;
27945916cd2Sjpk 		return (0);
28045916cd2Sjpk 	} else if (rval == NOSERVER) {
28145916cd2Sjpk 		char *s = (char *)string;
28245916cd2Sjpk 
28345916cd2Sjpk 		if (callp != &call) {
28445916cd2Sjpk 			/* free allocated buffer */
28545916cd2Sjpk 			free(callp);
28645916cd2Sjpk 		}
28745916cd2Sjpk 		/* server not present */
28845916cd2Sjpk 		/* special case Admin High and Admin Low */
28945916cd2Sjpk 		while (isspace(*s))
29045916cd2Sjpk 			s++;
29145916cd2Sjpk 		if (IS_ADMIN_LOW(s)) {
29245916cd2Sjpk 			BCLEARLOW(clearance);
29345916cd2Sjpk 		} else if (IS_ADMIN_HIGH(s)) {
29445916cd2Sjpk 			BCLEARHIGH(clearance);
29545916cd2Sjpk 		} else {
29645916cd2Sjpk 			goto err1;
29745916cd2Sjpk 		}
29845916cd2Sjpk 		return (1);
29945916cd2Sjpk 	}
30045916cd2Sjpk 	if (callp != &call) {
30145916cd2Sjpk 		/* free allocated buffer */
30245916cd2Sjpk 		free(callp);
30345916cd2Sjpk 	}
30445916cd2Sjpk err1:
30545916cd2Sjpk 	if (error != NULL)
30645916cd2Sjpk 		*error = -1;
30745916cd2Sjpk 	return (0);
30845916cd2Sjpk }  /* stobclear */
30945916cd2Sjpk #undef	clrcall
31045916cd2Sjpk #undef	clrret
311