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 2007 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 *	String to binary label translations.
30 */
31
32#include <ctype.h>
33#include <locale.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <strings.h>
37
38#include <tsol/label.h>
39
40#include "labeld.h"
41#include <sys/tsol/label_macro.h>
42
43#undef	CALL_SIZE
44#define	CALL_SIZE(type, buf)	(size_t)(sizeof (type) - BUFSIZE + sizeof (int)\
45	+ (buf))
46
47#if	!defined(TEXT_DOMAIN)		/* should be defined by Makefiles */
48#define	TEXT_DOMAIN "SYS_TEST"
49#endif	/* TEXT_DOMAIN */
50
51/* short hands */
52
53#define	IS_ADMIN_LOW(sl) \
54	((strncasecmp(sl, ADMIN_LOW, (sizeof (ADMIN_LOW) - 1)) == 0))
55
56#define	IS_ADMIN_HIGH(sh) \
57	((strncasecmp(sh, ADMIN_HIGH, (sizeof (ADMIN_HIGH) - 1)) == 0))
58
59#define	ISHEX(f, s) \
60	(((((f) & NEW_LABEL) == ((f) | NEW_LABEL)) || \
61	(((f) & NO_CORRECTION) == ((f) | NO_CORRECTION))) && \
62	(((s)[0] == '0') && (((s)[1] == 'x') || ((s)[1] == 'X'))))
63
64#define	slcall callp->param.acall.cargs.stobsl_arg
65#define	slret callp->param.aret.rvals.stobsl_ret
66/*
67 *	stobsl - Translate Sensitivity Label string to a Binary Sensitivity
68 *		Label.
69 *
70 *	Entry	string = Sensitivity Label string to be translated.
71 *		label = Address of Binary Sensitivity Label to be initialized or
72 *			updated.
73 *		flags = Flags to control translation:
74 *			NO_CORRECTION implies NEW_LABEL.
75 *			NEW_LABEL, Initialize the label to a valid empty
76 *				Sensitivity Label structure.
77 *			NO_CORRECTION, Initialize the label to a valid
78 *				empty Sensitivity Label structure.
79 *				Prohibit correction to the Sensitivity Label.
80 *			Other, pass existing Sensitivity Label through for
81 *				modification.
82 *
83 *	Exit	label = Translated (updated) Binary Sensitivity Label.
84 *		error = If error reported, the error indicator,
85 *				-1, Unable to access label encodings file;
86 *				 0, Invalid binary label passed;
87 *				>0, Position after the first character in
88 *				    string of error, 1 indicates entire string.
89 *			Otherwise, unchanged.
90 *
91 *	Returns	0, If error.
92 *		1, If successful.
93 *
94 *	Calls	__call_labeld(STOBSL), ISHEX, htobsl, strlen,
95 *			isspace,
96 *			strncasecmp.
97 *
98 *	Uses	ADMIN_HIGH, ADMIN_LOW.
99 */
100
101int
102stobsl(const char *string, bslabel_t *label, int flags, int *error)
103{
104	labeld_data_t	call;
105	labeld_data_t	*callp = &call;
106	size_t	bufsize = sizeof (labeld_data_t);
107	size_t	datasize = CALL_SIZE(stobsl_call_t, strlen(string) + 1);
108	int	rval;
109	char	*s = (char *)string;
110
111	while (isspace(*s))
112		s++;
113	/* accept a leading '[' */
114	if (*s == '[') {
115		s++;
116		while (isspace(*s))
117			s++;
118	}
119	if (ISHEX(flags, s)) {
120		if (htobsl(s, label)) {
121			return (1);
122		} else {
123			if (error != NULL)
124				*error = 1;
125			return (0);
126		}
127	}
128
129	if (datasize > bufsize) {
130		if ((callp = malloc(datasize)) == NULL) {
131			if (error != NULL)
132				*error = -1;
133			return (0);
134		}
135		bufsize = datasize;
136	}
137	callp->callop = STOBSL;
138	slcall.flags  = (flags&NEW_LABEL) ? LABELS_NEW_LABEL : 0;
139	slcall.flags |= (flags&NO_CORRECTION) ? LABELS_FULL_PARSE : 0;
140	slcall.label = *label;
141	(void) strcpy(slcall.string, string);
142
143	if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) {
144		int err = callp->reterr;
145
146		if (callp != &call) {
147			/* free allocated buffer */
148			free(callp);
149		}
150		/*
151		 * reterr == 0, OK,
152		 * reterr < 0, invalid binary label,
153		 * reterr > 0 error position, 1 == whole string
154		 */
155		if (err == 0) {
156			*label = slret.label;
157			return (1);
158		} else if (err < 0) {
159			err = 0;
160		}
161		if (error != NULL)
162			*error = err;
163		return (0);
164	} else if (rval == NOSERVER) {
165		if (callp != &call) {
166			/* free allocated buffer */
167			free(callp);
168		}
169		/* server not present */
170		/* special case Admin High and Admin Low */
171		if (IS_ADMIN_LOW(s)) {
172			BSLLOW(label);
173		} else if (IS_ADMIN_HIGH(s)) {
174			BSLHIGH(label);
175		} else {
176			goto err1;
177		}
178		return (1);
179	}
180	if (callp != &call) {
181		/* free allocated buffer */
182		free(callp);
183	}
184err1:
185	if (error != NULL)
186		*error = -1;
187	return (0);
188}  /* stobsl */
189#undef	slcall
190#undef	slret
191
192#define	clrcall callp->param.acall.cargs.stobclear_arg
193#define	clrret callp->param.aret.rvals.stobclear_ret
194/*
195 *	stobclear - Translate Clearance string to a Binary Clearance.
196 *
197 *	Entry	string = Clearance string to be translated.
198 *		clearance = Address of Binary Clearance to be initialized or
199 *			updated.
200 *		flags = Flags to control translation:
201 *			NO_CORRECTION implies NEW_LABEL.
202 *			NEW_LABEL, Initialize the label to a valid empty
203 *				Sensitivity Label structure.
204 *			NO_CORRECTION, Initialize the label to a valid
205 *				empty Sensitivity Label structure.
206 *				Prohibit correction to the Sensitivity Label.
207 *			Other, pass existing Sensitivity Label through for
208 *				modification.
209 *
210 *	Exit	clearance = Translated (updated) Binary Clearance.
211 *		error = If error reported, the error indicator,
212 *				-1, Unable to access label encodings file;
213 *				 0, Invalid binary label passed;
214 *				>0, Position after the first character in
215 *				    string of error, 1 indicates entire string.
216 *			Otherwise, unchanged.
217 *
218 *	Returns	0, If error.
219 *		1, If successful.
220 *
221 *	Calls	__call_labeld(STOBCLEAR), ISHEX, htobsl, strlen,
222 *			isspace,
223 *			strncasecmp.
224 *
225 *	Uses	ADMIN_HIGH, ADMIN_LOW.
226 */
227
228int
229stobclear(const char *string, bclear_t *clearance, int flags, int *error)
230{
231	labeld_data_t	call;
232	labeld_data_t	*callp = &call;
233	size_t	bufsize = sizeof (labeld_data_t);
234	size_t	datasize = CALL_SIZE(stobclear_call_t, strlen(string) + 1);
235	int	rval;
236
237	if (ISHEX(flags, string)) {
238		if (htobclear(string, clearance)) {
239			return (1);
240		} else {
241			if (error != NULL)
242				*error = 1;
243			return (0);
244		}
245	}
246
247	if (datasize > bufsize) {
248		if ((callp = malloc(datasize)) == NULL) {
249			if (error != NULL)
250				*error = -1;
251			return (0);
252		}
253		bufsize = datasize;
254	}
255	callp->callop = STOBCLEAR;
256	clrcall.flags  = (flags&NEW_LABEL) ? LABELS_NEW_LABEL : 0;
257	clrcall.flags |= (flags&NO_CORRECTION) ? LABELS_FULL_PARSE : 0;
258	clrcall.clear = *clearance;
259	(void) strcpy(clrcall.string, string);
260
261	if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) {
262		int err = callp->reterr;
263
264		if (callp != &call) {
265			/* free allocated buffer */
266			free(callp);
267		}
268		/*
269		 * reterr == 0, OK,
270		 * reterr < 0, invalid binary label,
271		 * reterr > 0 error position, 1 == whole string
272		 */
273		if (err == 0) {
274			*clearance = clrret.clear;
275			return (1);
276		} else if (err < 0) {
277			err = 0;
278		}
279		if (error != NULL)
280			*error = err;
281		return (0);
282	} else if (rval == NOSERVER) {
283		char *s = (char *)string;
284
285		if (callp != &call) {
286			/* free allocated buffer */
287			free(callp);
288		}
289		/* server not present */
290		/* special case Admin High and Admin Low */
291		while (isspace(*s))
292			s++;
293		if (IS_ADMIN_LOW(s)) {
294			BCLEARLOW(clearance);
295		} else if (IS_ADMIN_HIGH(s)) {
296			BCLEARHIGH(clearance);
297		} else {
298			goto err1;
299		}
300		return (1);
301	}
302	if (callp != &call) {
303		/* free allocated buffer */
304		free(callp);
305	}
306err1:
307	if (error != NULL)
308		*error = -1;
309	return (0);
310}  /* stobclear */
311#undef	clrcall
312#undef	clrret
313