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 /*
27 * Binary label to label string translations.
28 */
29
30 #include <locale.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <wchar.h>
36
37 #include <sys/mman.h>
38
39 #include <tsol/label.h>
40
41 #include "clnt.h"
42 #include "labeld.h"
43 #include <sys/tsol/label_macro.h>
44
45 #if !defined(TEXT_DOMAIN) /* should be defined by Makefiles */
46 #define TEXT_DOMAIN "SYS_TEST"
47 #endif /* TEXT_DOMAIN */
48
49 static bslabel_t slow; /* static admin_low high sensitivity label */
50 static bslabel_t shigh; /* static admin_high sensitivity label */
51 static bclear_t clrlow, clrhigh; /* static admin_low and admin_high Clearance */
52
53 static char *sstring; /* return string for sb*tos */
54 static size_t ssize; /* current size of return string */
55
56 static int
return_string(char ** string,int str_len,char * val)57 return_string(char **string, int str_len, char *val)
58 {
59 char *cpyptr;
60 size_t val_len = strlen(val) + 1;
61
62 if (*string == NULL) {
63 if ((*string = malloc(val_len)) == NULL)
64 return (0);
65 } else if (val_len > str_len) {
66 **string = '\0';
67 return (0);
68 }
69
70 cpyptr = *string;
71 bcopy(val, cpyptr, val_len);
72
73 return (val_len);
74 }
75
76 void
set_label_view(uint_t * callflags,uint_t flags)77 set_label_view(uint_t *callflags, uint_t flags)
78 {
79 if (flags&VIEW_INTERNAL) {
80 *callflags |= LABELS_VIEW_INTERNAL;
81 } else if (flags&VIEW_EXTERNAL) {
82 *callflags |= LABELS_VIEW_EXTERNAL;
83 }
84 }
85
86 int
alloc_string(char ** string,size_t size,char val)87 alloc_string(char **string, size_t size, char val)
88 {
89 if (*string == NULL) {
90 if ((*string = malloc(ALLOC_CHUNK)) == NULL)
91 return (0);
92 } else {
93 if ((*string = realloc(*string, size + ALLOC_CHUNK)) == NULL) {
94 **string = val;
95 return (0);
96 }
97 }
98 **string = val;
99 return (ALLOC_CHUNK);
100 }
101
102 #define slcall callp->param.acall.cargs.bsltos_arg
103 #define slret callp->param.aret.rvals.bsltos_ret
104 /*
105 * bsltos - Convert Binary Sensitivity Label to Sensitivity Label string.
106 *
107 * Entry label = Binary Sensitivity Label to be converted.
108 * string = NULL ((char *) 0), if memory to be allocated,
109 * otherwise, pointer to preallocated memory.
110 * str_len = Length of preallocated memory, else ignored.
111 * flags = Logical sum of:
112 * LONG_CLASSIFICATION or SHORT_CLASSIFICATION,
113 * LONG_WORDS or SHORT_WORDS,
114 * VIEW_INTERNAL or VIEW_EXTERNAL, and
115 * NO_CLASSIFICATION.
116 * LONG_CLASSIFICATION, use long classification names.
117 * SHORT_CLASSIFICATION, use short classification
118 * names (default).
119 * NO_CLASSIFICATION, don't translate classification.
120 * LONG_WORDS, use the long form of words (default).
121 * SHORTWORDS, use the short form of words where available.
122 * VIEW_INTERNAL, don't promote/demote admin low/high.
123 * VIEW_EXTERNAL, promote/demote admin low/high.
124 *
125 * Exit string = Sensitivity Label string, or empty string if
126 * not enough preallocated memory.
127 *
128 * Returns -1, If unable to access label encodings database.
129 * 0, If unable to allocate string,
130 * or allocated string to short
131 * (and **string = '\0').
132 * length (including null) of Sensitivity Label string,
133 * If successful.
134 *
135 * Calls RPC - LABELS_BSLTOS, BCLHIGH, BCLLOW, BCLTOSL, BLEQUAL,
136 * BLTYPE, SETBSLABEL, UCLNT, memcpy, clnt_call,
137 * clnt_perror, malloc, strcat, strlen.
138 *
139 * Uses ADMIN_HIGH, ADMIN_LOW, shigh, slow.
140 */
141
142 ssize_t
bsltos(const bslabel_t * label,char ** string,size_t str_len,int flags)143 bsltos(const bslabel_t *label, char **string, size_t str_len,
144 int flags)
145 {
146 labeld_data_t call;
147 labeld_data_t *callp = &call;
148 size_t bufsize = sizeof (labeld_data_t);
149 size_t datasize = CALL_SIZE(bsltos_call_t, 0);
150 int rval;
151
152 if (!BLTYPE(label, SUN_SL_ID)) {
153 return (-1);
154 }
155
156 call.callop = BSLTOS;
157 slcall.label = *label;
158 slcall.flags = (flags&NO_CLASSIFICATION) ? LABELS_NO_CLASS : 0;
159 slcall.flags |= (flags&SHORT_CLASSIFICATION ||
160 !(flags&LONG_CLASSIFICATION)) ? LABELS_SHORT_CLASS : 0;
161 slcall.flags |= (flags&SHORT_WORDS && !(flags&LONG_WORDS)) ?
162 LABELS_SHORT_WORDS : 0;
163 set_label_view(&slcall.flags, flags);
164
165 if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) {
166
167 if (callp->reterr != 0)
168 return (-1);
169
170 /* unpack Sensitivity Label */
171
172 rval = return_string(string, str_len, slret.slabel);
173
174 if (callp != &call)
175 (void) munmap((void *)callp, bufsize);
176 return (rval);
177 } else if (rval == NOSERVER) {
178 /* server not present */
179 /* special case admin_high and admin_low */
180
181 if (!BLTYPE(&slow, SUN_SL_ID)) {
182 /* initialize static labels */
183
184 BSLLOW(&slow);
185 BSLHIGH(&shigh);
186 }
187
188 if (BLEQUAL(label, &slow)) {
189 return (return_string(string, str_len, ADMIN_LOW));
190 } else if (BLEQUAL(label, &shigh)) {
191 return (return_string(string, str_len, ADMIN_HIGH));
192 }
193 }
194 return (-1);
195 } /* bsltos */
196 #undef slcall
197 #undef slret
198
199 #define clrcall callp->param.acall.cargs.bcleartos_arg
200 #define clrret callp->param.aret.rvals.bcleartos_ret
201 /*
202 * bcleartos - Convert Binary Clearance to Clearance string.
203 *
204 * Entry clearance = Binary Clearance to be converted.
205 * string = NULL ((char *) 0), if memory to be allocated,
206 * otherwise, pointer to preallocated memory.
207 * str_len = Length of preallocated memory, else ignored.
208 * flags = Logical sum of:
209 * LONG_CLASSIFICATION or SHORT_CLASSIFICATION,
210 * LONG_WORDS or SHORT_WORDS,
211 * VIEW_INTERNAL or VIEW_EXTERNAL.
212 * LONG_CLASSIFICATION, use long classification names.
213 * SHORT_CLASSIFICATION, use short classification
214 * names (default).
215 * LONG_WORDS, use the long form of words (default).
216 * SHORTWORDS, use the short form of words where available.
217 * VIEW_INTERNAL, don't promote/demote admin low/high.
218 * VIEW_EXTERNAL, promote/demote admin low/high.
219 *
220 * Exit string = Clearance string, or empty string if not
221 * enough preallocated memory.
222 *
223 * Returns -1, If unable to access label encodings database.
224 * 0, If unable to allocate string,
225 * or allocated string to short
226 * (and **string = '\0').
227 * length (including null) of Clearance string,
228 * If successful.
229 *
230 * Calls RPC - LABELS_BSLTOS, BCLHIGH, BCLLOW, BCLTOSL, BLEQUAL,
231 * BLTYPE, SETBSLABEL, UCLNT, memcpy, clnt_call,
232 * clnt_perror, malloc, strcat, strlen.
233 *
234 * Uses ADMIN_HIGH, ADMIN_LOW, clrhigh, clrlow.
235 */
236
237 ssize_t
bcleartos(const bclear_t * clearance,char ** string,size_t str_len,int flags)238 bcleartos(const bclear_t *clearance, char **string, size_t str_len,
239 int flags)
240 {
241 labeld_data_t call;
242 labeld_data_t *callp = &call;
243 size_t bufsize = sizeof (labeld_data_t);
244 size_t datasize = CALL_SIZE(bcleartos_call_t, 0);
245 int rval;
246
247 if (!BLTYPE(clearance, SUN_CLR_ID)) {
248 return (-1);
249 }
250
251 call.callop = BCLEARTOS;
252 clrcall.clear = *clearance;
253 clrcall.flags = (flags&SHORT_CLASSIFICATION ||
254 !(flags&LONG_CLASSIFICATION)) ? LABELS_SHORT_CLASS : 0;
255 clrcall.flags |= (flags&SHORT_WORDS && !(flags&LONG_WORDS)) ?
256 LABELS_SHORT_WORDS : 0;
257 set_label_view(&clrcall.flags, flags);
258
259 if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == SUCCESS) {
260
261 if (callp->reterr != 0)
262 return (-1);
263
264 /* unpack Clearance */
265
266 rval = return_string(string, str_len, clrret.cslabel);
267
268 if (callp != &call)
269 /* release return buffer */
270 (void) munmap((void *)callp, bufsize);
271 return (rval);
272 } else if (rval == NOSERVER) {
273 /* server not present */
274 /* special case admin_high and admin_low */
275
276 if (!BLTYPE(&clrlow, SUN_CLR_ID)) {
277 /* initialize static labels */
278
279 BCLEARLOW(&clrlow);
280 BCLEARHIGH(&clrhigh);
281 }
282 if (BLEQUAL(clearance, &clrlow)) {
283 return (return_string(string, str_len, ADMIN_LOW));
284 } else if (BLEQUAL(clearance, &clrhigh)) {
285 return (return_string(string, str_len, ADMIN_HIGH));
286 }
287 }
288 return (-1);
289 } /* bcleartos */
290 #undef clrcall
291 #undef clrret
292
293 /*
294 * sbsltos - Convert Sensitivity Label to canonical clipped form.
295 *
296 * Entry label = Sensitivity Label to be converted.
297 * len = Maximum length of translated string, excluding NULL.
298 * 0, full string.
299 * sstring = address of string to translate into.
300 * ssize = size of memory currently allocated to sstring.
301 *
302 * Exit sstring = Newly translated string.
303 * ssize = Updated if more memory pre-allocated.
304 *
305 * Returns NULL, If error, len too small, unable to translate, or get
306 * memory for string.
307 * Address of string containing converted value.
308 *
309 * Calls alloc_string, bsltos, strcpy.
310 *
311 * Uses ssize, sstring.
312 */
313
314 char *
sbsltos(const bslabel_t * label,size_t len)315 sbsltos(const bslabel_t *label, size_t len)
316 {
317 ssize_t slen; /* length including NULL */
318 wchar_t *wstring;
319 int wccount;
320
321 if (ssize == 0) {
322 /* Allocate string memory. */
323 if ((ssize = alloc_string(&sstring, ssize, 's')) == 0)
324 /* can't get initial memory for string */
325 return (NULL);
326 }
327
328 again:
329 if ((slen = bsltos(label, &sstring, ssize,
330 (SHORT_CLASSIFICATION | LONG_WORDS))) <= 0) {
331 /* error in translation */
332 if (slen == 0) {
333 if (*sstring == '\0') {
334 int newsize;
335 /* sstring not long enough */
336 if ((newsize = alloc_string(&sstring, ssize,
337 's')) == 0) {
338 /* Can't get more memory */
339 return (NULL);
340 }
341 ssize += newsize;
342 goto again;
343 }
344 }
345 return (NULL);
346 }
347 if (len == 0) {
348 return (sstring);
349 } else if (len < MIN_SL_LEN) {
350 return (NULL);
351 }
352 if ((wstring = malloc(slen * sizeof (wchar_t))) == NULL)
353 return (NULL);
354 if ((wccount = mbstowcs(wstring, sstring, slen - 1)) == -1) {
355 free(wstring);
356 return (NULL);
357 }
358 if (wccount > len) {
359 wchar_t *clipp = wstring + (len - 2);
360
361 /* Adjust string size to desired length */
362
363 clipp[0] = L'<';
364 clipp[1] = L'-';
365 clipp[2] = L'\0';
366
367 while (wcstombs(NULL, wstring, 0) >= ssize) {
368 int newsize;
369
370 /* sstring not long enough */
371 if ((newsize = alloc_string(&sstring, ssize, 's')) ==
372 0) {
373 /* Can't get more memory */
374 return (NULL);
375 }
376 ssize += newsize;
377 }
378
379 if ((wccount = wcstombs(sstring, wstring, ssize)) == -1) {
380 free(wstring);
381 return (NULL);
382 }
383 }
384 free(wstring);
385
386 return (sstring);
387 } /* sbsltos */
388
389 /*
390 * sbcleartos - Convert Clearance to canonical clipped form.
391 *
392 * Entry clearance = Clearance to be converted.
393 * len = Maximum length of translated string, excluding NULL.
394 * 0, full string.
395 * sstring = address of string to translate into.
396 * ssize = size of memory currently allocated to sstring.
397 *
398 * Exit sstring = Newly translated string.
399 * ssize = Updated if more memory pre-allocated.
400 *
401 * Returns NULL, If error, len too small, unable to translate, or get
402 * memory for string.
403 * Address of string containing converted value.
404 *
405 * Calls alloc_string, bcleartos, strcpy.
406 *
407 * Uses ssize, sstring.
408 */
409
410 char *
sbcleartos(const bclear_t * clearance,size_t len)411 sbcleartos(const bclear_t *clearance, size_t len)
412 {
413 ssize_t slen; /* length including NULL */
414 wchar_t *wstring;
415 int wccount;
416
417 if (ssize == 0) {
418 /* Allocate string memory. */
419 if ((ssize = alloc_string(&sstring, ssize, 'c')) == 0)
420 /* can't get initial memory for string */
421 return (NULL);
422 }
423
424 again:
425 if ((slen = bcleartos(clearance, &sstring, ssize,
426 (SHORT_CLASSIFICATION | LONG_WORDS))) <= 0) {
427 /* error in translation */
428 if (slen == 0) {
429 if (*sstring == '\0') {
430 int newsize;
431 /* sstring not long enough */
432 if ((newsize = alloc_string(&sstring, ssize,
433 'c')) == 0) {
434 /* Can't get more memory */
435 return (NULL);
436 }
437 ssize += newsize;
438 goto again;
439 }
440 }
441 return (NULL);
442 }
443 if (len == 0) {
444 return (sstring);
445 } else if (len < MIN_CLR_LEN) {
446 return (NULL);
447 }
448 if ((wstring = malloc(slen * sizeof (wchar_t))) == NULL)
449 return (NULL);
450 if ((wccount = mbstowcs(wstring, sstring, slen - 1)) == -1) {
451 free(wstring);
452 return (NULL);
453 }
454 if (wccount > len) {
455 wchar_t *clipp = wstring + (len - 2);
456
457 /* Adjust string size to desired length */
458
459 clipp[0] = L'<';
460 clipp[1] = L'-';
461 clipp[2] = L'\0';
462
463 while (wcstombs(NULL, wstring, 0) >= ssize) {
464 int newsize;
465
466 /* sstring not long enough */
467 if ((newsize = alloc_string(&sstring, ssize, 'c')) ==
468 0) {
469 /* Can't get more memory */
470 free(wstring);
471 return (NULL);
472 }
473 ssize += newsize;
474 }
475 if ((wccount = wcstombs(sstring, wstring, ssize)) == -1) {
476 free(wstring);
477 return (NULL);
478 }
479 }
480 free(wstring);
481
482 return (sstring);
483 } /* sbcleartos */
484