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
return_string(char ** string,int str_len,char * val)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
set_label_view(uint_t * callflags,uint_t flags)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
alloc_string(char ** string,size_t size,char val)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
bsltos(const bslabel_t * label,char ** string,size_t str_len,int flags)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
bcleartos(const bclear_t * clearance,char ** string,size_t str_len,int flags)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 *
sbsltos(const bslabel_t * label,size_t len)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 *
sbcleartos(const bclear_t * clearance,size_t len)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