1 
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <assert.h>
5 
6 #include <string.h>
7 
8 #define xstreq(x, y) !strcmp(x, y)
9 
10 #include <err.h>
11 
12 #include <getopt.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15 #include <selinux/selinux.h>
16 #include <selinux/context.h>
17 
18 #define TRUE  1
19 #define FALSE 0
20 
21 #define SECON_CONF_PROG_NAME "secon"	/* default program name */
22 #define SECON_OPTS_SM "hVurtscmPRCfLp"	/* small options available, print */
23 #define SECON_OPTS_GO "hVurtlscmPRCf:L:p:"	/* small options available, getopt */
24 
25 #define OPTS_FROM_ARG      0
26 #define OPTS_FROM_FILE     1
27 #define OPTS_FROM_LINK     2
28 #define OPTS_FROM_STDIN    3
29 #define OPTS_FROM_CUR      4
30 #define OPTS_FROM_CUREXE   5
31 #define OPTS_FROM_CURFS    6
32 #define OPTS_FROM_CURKEY   7
33 #define OPTS_FROM_PROC     8
34 #define OPTS_FROM_PROCEXE  9
35 #define OPTS_FROM_PROCFS   10
36 #define OPTS_FROM_PROCKEY  11
37 
38 struct context_color_t {
39 	unsigned int valid;
40 
41 	char *user_fg;
42 	char *user_bg;
43 	char *role_fg;
44 	char *role_bg;
45 	char *type_fg;
46 	char *type_bg;
47 	char *range_fg;
48 	char *range_bg;
49 };
50 
51 struct {
52 	unsigned int disp_user:1;
53 	unsigned int disp_role:1;
54 	unsigned int disp_type:1;
55 	unsigned int disp_sen:1;
56 	unsigned int disp_clr:1;
57 	unsigned int disp_mlsr:1;
58 
59 	unsigned int disp_raw:1;
60 	unsigned int disp_color:1;
61 
62 	unsigned int disp_prompt:1;	/* no return, use : to sep */
63 
64 	unsigned int from_type:8;	/* 16 bits, uses 4 bits */
65 
66 	union {
67 		pid_t pid;
68 		const char *file;
69 		const char *link;
70 		const char *arg;
71 	} f;
72 } opts[1] = { {
73 		FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
74 		    FALSE, FALSE, FALSE, OPTS_FROM_ARG, {0} } };
75 
usage(const char * name,int exit_code)76 static void usage(const char *name, int exit_code)
77 {
78 	fprintf(exit_code ? stderr : stdout,
79 		"  Usage: %s [-%s] [ context | - ]\n"
80 		"          --help        -h     Show this message.\n"
81 		"          --version     -V     Show the version.\n"
82 		"          --prompt      -P     Output in a format good for a prompt.\n"
83 		"          --user        -u     Show the user of the context.\n"
84 		"          --role        -r     Show the role of the context.\n"
85 		"          --type        -t     Show the type of the context.\n"
86 		"          --sensitivity -s     Show the sensitivity level of the context.\n"
87 		"          --clearance   -c     Show the clearance level of the context.\n"
88 		"          --mls-range   -m     Show the sensitivity to clearance range of \n"
89 		"                               the context.\n"
90 		"          --raw         -R     Show the context in \"raw\" format.\n"
91 		"          --color       -C     Output using ANSI color codes (requires -P).\n"
92 		"          --current            Get the context for the current process.\n"
93 		"          --self               Get the context for the current process.\n"
94 		"          --self-exec          Get the exec context for the current process.\n"
95 		"          --self-fs            Get the fs context for the current process.\n"
96 		"          --self-key           Get the key context for the current process.\n"
97 		"          --parent             Get the context for the parent process.\n"
98 		"          --parent-exec        Get the exec context for the parent process.\n"
99 		"          --parent-fs          Get the fs context for the parent process.\n"
100 		"          --parent-key         Get the key context for the parent process.\n"
101 		"          --pid       -p <arg> Use the context from the specified pid.\n"
102 		"          --pid-exec     <arg> Use the exec context from the specified pid.\n"
103 		"          --pid-fs       <arg> Use the fs context from the specified pid.\n"
104 		"          --pid-key      <arg> Use the key context from the specified pid.\n"
105 		"          --file      -f <arg> Use the context from the specified file.\n"
106 		"          --link      -L <arg> Use the context from the specified link.\n",
107 		name, SECON_OPTS_SM);
108 
109 	exit(exit_code);
110 }
111 
opt_program_name(const char * argv0,const char * def)112 static const char *opt_program_name(const char *argv0, const char *def)
113 {
114 	if (argv0) {
115 		if ((def = strrchr(argv0, '/')))
116 			++def;
117 		else
118 			def = argv0;
119 
120 		/* hack for libtool */
121 		if ((strlen(def) > strlen("lt-"))
122 		    && !memcmp("lt-", def, strlen("lt-")))
123 			def += 3;
124 	}
125 
126 	return (def);
127 }
128 
disp_num(void)129 static int disp_num(void)
130 {
131 	int num = 0;
132 
133 	num += opts->disp_user;
134 	num += opts->disp_role;
135 	num += opts->disp_type;
136 	num += opts->disp_sen;
137 	num += opts->disp_clr;
138 	num += opts->disp_mlsr;
139 
140 	return (num);
141 }
142 
disp_none(void)143 static int disp_none(void)
144 {
145 	return (!disp_num());
146 }
147 
disp_multi(void)148 static int disp_multi(void)
149 {
150 	return (disp_num() > 1);
151 }
152 
cmd_line(int argc,char * argv[])153 static void cmd_line(int argc, char *argv[])
154 {
155 	int optchar = 0;
156 	const char *program_name = NULL;
157 	struct option long_options[] = {
158 		{"help", no_argument, NULL, 'h'},
159 		{"version", no_argument, NULL, 'V'},
160 
161 		{"prompt", no_argument, NULL, 'P'},
162 
163 		{"user", no_argument, NULL, 'u'},
164 		{"role", no_argument, NULL, 'r'},
165 		{"type", no_argument, NULL, 't'},
166 		{"level", no_argument, NULL, 'l'},	/* compat. */
167 		{"sensitivity", no_argument, NULL, 's'},
168 		{"range", no_argument, NULL, 'm'},
169 		{"clearance", no_argument, NULL, 'c'},
170 		{"mls-range", no_argument, NULL, 'm'},
171 
172 		{"raw", no_argument, NULL, 'R'},
173 		{"color", no_argument, NULL, 'C'},
174 
175 		{"current", no_argument, NULL, 1},
176 		{"self", no_argument, NULL, 1},
177 		{"current-exec", no_argument, NULL, 2},
178 		{"self-exec", no_argument, NULL, 2},
179 		{"current-fs", no_argument, NULL, 3},
180 		{"self-fs", no_argument, NULL, 3},
181 		{"current-key", no_argument, NULL, 4},
182 		{"self-key", no_argument, NULL, 4},
183 
184 		{"parent", no_argument, NULL, 5},
185 		{"parent-exec", no_argument, NULL, 6},
186 		{"parent-fs", no_argument, NULL, 7},
187 		{"parent-key", no_argument, NULL, 8},
188 
189 		{"file", required_argument, NULL, 'f'},
190 		{"link", required_argument, NULL, 'L'},
191 		{"pid", required_argument, NULL, 'p'},
192 		{"pid-exec", required_argument, NULL, 9},
193 		{"pid-fs", required_argument, NULL, 10},
194 		{"pid-key", required_argument, NULL, 11},
195 
196 		{NULL, 0, NULL, 0}
197 	};
198 	int done = FALSE;
199 
200 	program_name = opt_program_name(argv[0], SECON_CONF_PROG_NAME);
201 
202 	while ((optchar = getopt_long(argc, argv, SECON_OPTS_GO,
203 				      long_options, NULL)) != -1) {
204 		switch (optchar) {
205 		case '?':
206 			usage(program_name, EXIT_FAILURE);
207 		case 'h':
208 			usage(program_name, EXIT_SUCCESS);
209 		case 'V':
210 			fprintf(stdout,
211 				" %s version %s.\n", program_name, VERSION);
212 			exit(EXIT_SUCCESS);
213 
214 		case 'u':
215 			done = TRUE;
216 			opts->disp_user = !opts->disp_user;
217 			break;
218 		case 'r':
219 			done = TRUE;
220 			opts->disp_role = !opts->disp_role;
221 			break;
222 		case 't':
223 			done = TRUE;
224 			opts->disp_type = !opts->disp_type;
225 			break;
226 		case 'l':
227 			done = TRUE;
228 			opts->disp_sen = !opts->disp_sen;
229 			break;
230 		case 's':
231 			done = TRUE;
232 			opts->disp_sen = !opts->disp_sen;
233 			break;
234 		case 'c':
235 			done = TRUE;
236 			opts->disp_clr = !opts->disp_clr;
237 			break;
238 		case 'm':
239 			done = TRUE;
240 			opts->disp_mlsr = !opts->disp_mlsr;
241 			break;
242 
243 		case 'P':
244 			opts->disp_prompt = !opts->disp_prompt;
245 			break;
246 
247 		case 'R':
248 			opts->disp_raw = !opts->disp_raw;
249 			break;
250 		case 'C':
251 			opts->disp_color = !opts->disp_color;
252 			break;
253 		case 1:
254 			opts->from_type = OPTS_FROM_CUR;
255 			break;
256 		case 2:
257 			opts->from_type = OPTS_FROM_CUREXE;
258 			break;
259 		case 3:
260 			opts->from_type = OPTS_FROM_CURFS;
261 			break;
262 		case 4:
263 			opts->from_type = OPTS_FROM_CURKEY;
264 			break;
265 
266 		case 5:
267 			opts->from_type = OPTS_FROM_PROC;
268 			opts->f.pid = getppid();
269 			break;
270 		case 6:
271 			opts->from_type = OPTS_FROM_PROCEXE;
272 			opts->f.pid = getppid();
273 			break;
274 		case 7:
275 			opts->from_type = OPTS_FROM_PROCFS;
276 			opts->f.pid = getppid();
277 			break;
278 		case 8:
279 			opts->from_type = OPTS_FROM_PROCKEY;
280 			opts->f.pid = getppid();
281 			break;
282 
283 		case 'f':
284 			opts->from_type = OPTS_FROM_FILE;
285 			opts->f.file = optarg;
286 			break;
287 		case 'L':
288 			opts->from_type = OPTS_FROM_LINK;
289 			opts->f.link = optarg;
290 			break;
291 		case 'p':
292 			opts->from_type = OPTS_FROM_PROC;
293 			opts->f.pid = atoi(optarg);
294 			break;
295 		case 9:
296 			opts->from_type = OPTS_FROM_PROCEXE;
297 			opts->f.pid = atoi(optarg);
298 			break;
299 		case 10:
300 			opts->from_type = OPTS_FROM_PROCFS;
301 			opts->f.pid = atoi(optarg);
302 			break;
303 		case 11:
304 			opts->from_type = OPTS_FROM_PROCKEY;
305 			opts->f.pid = atoi(optarg);
306 			break;
307 
308 		default:
309 			assert(FALSE);
310 		}
311 	}
312 
313 	if (!done) {		/* defualt, if nothing specified */
314 		opts->disp_user = TRUE;
315 		opts->disp_role = TRUE;
316 		opts->disp_type = TRUE;
317 		if (!opts->disp_prompt) {	/* when displaying prompt, just output "normal" by default */
318 			opts->disp_sen = TRUE;
319 			opts->disp_clr = TRUE;
320 		}
321 		opts->disp_mlsr = TRUE;
322 	}
323 
324 	if (disp_none())
325 		err(EXIT_FAILURE, " Nothing to display");
326 
327 	argc -= optind;
328 	argv += optind;
329 
330 	if (!argc && (opts->from_type == OPTS_FROM_ARG)
331 	    && !isatty(STDIN_FILENO))
332 		opts->from_type = OPTS_FROM_STDIN;
333 	if (!argc && (opts->from_type == OPTS_FROM_ARG))
334 		opts->from_type = OPTS_FROM_CUR;
335 
336 	if (opts->from_type == OPTS_FROM_ARG) {
337 		opts->f.arg = argv[0];
338 
339 		if (xstreq(argv[0], "-"))
340 			opts->from_type = OPTS_FROM_STDIN;
341 	} else if (!is_selinux_enabled())
342 		errx(EXIT_FAILURE, "SELinux is not enabled");
343 }
344 
my_getXcon_raw(pid_t pid,security_context_t * con,const char * val)345 static int my_getXcon_raw(pid_t pid, security_context_t * con, const char *val)
346 {
347 	char buf[4096];
348 	FILE *fp = NULL;
349 	const char *ptr = NULL;
350 
351 	snprintf(buf, sizeof(buf), "%s/%ld/attr/%s", "/proc", (long int)pid,
352 		 val);
353 
354 	if (!(fp = fopen(buf, "rb")))
355 		return (-1);
356 
357 	ptr = fgets(buf, sizeof(buf), fp);
358 
359 	fclose(fp);
360 
361 	*con = NULL;
362 	if (ptr) {		/* return *con = NULL, when proc file is empty */
363 		char *tmp = strchr(ptr, '\n');
364 
365 		if (tmp)
366 			*tmp = 0;
367 
368 		if (*ptr && !(*con = strdup(ptr)))
369 			return (-1);
370 	}
371 
372 	return (0);
373 }
374 
my_getpidexeccon_raw(pid_t pid,security_context_t * con)375 static int my_getpidexeccon_raw(pid_t pid, security_context_t * con)
376 {
377 	return (my_getXcon_raw(pid, con, "exec"));
378 }
my_getpidfscreatecon_raw(pid_t pid,security_context_t * con)379 static int my_getpidfscreatecon_raw(pid_t pid, security_context_t * con)
380 {
381 	return (my_getXcon_raw(pid, con, "fscreate"));
382 }
my_getpidkeycreatecon_raw(pid_t pid,security_context_t * con)383 static int my_getpidkeycreatecon_raw(pid_t pid, security_context_t * con)
384 {
385 	return (my_getXcon_raw(pid, con, "keycreate"));
386 }
387 
get_scon(void)388 static security_context_t get_scon(void)
389 {
390 	static char dummy_NIL[1] = "";
391 	security_context_t con = NULL, con_tmp;
392 	int ret = -1;
393 
394 	switch (opts->from_type) {
395 	case OPTS_FROM_ARG:
396 		if (!(con_tmp = strdup(opts->f.arg)))
397 			err(EXIT_FAILURE,
398 			    " Couldn't allocate security context");
399 		if (selinux_trans_to_raw_context(con_tmp, &con) < 0)
400 			err(EXIT_FAILURE,
401 			    " Couldn't translate security context");
402 		freecon(con_tmp);
403 		break;
404 
405 	case OPTS_FROM_STDIN:
406 		{
407 			char buf[4096] = "";
408 			char *ptr = buf;
409 
410 			while (!*ptr) {
411 				if (!(ptr = fgets(buf, sizeof(buf), stdin)))
412 					err(EXIT_FAILURE,
413 					    " Couldn't read security context");
414 
415 				ptr += strspn(ptr, " \n\t");
416 				ptr[strcspn(ptr, " \n\t")] = 0;
417 			}
418 
419 			if (!(con_tmp = strdup(ptr)))
420 				err(EXIT_FAILURE,
421 				    " Couldn't allocate security context");
422 			if (selinux_trans_to_raw_context(con_tmp, &con) < 0)
423 				err(EXIT_FAILURE,
424 				    " Couldn't translate security context");
425 			freecon(con_tmp);
426 			break;
427 		}
428 
429 	case OPTS_FROM_CUR:
430 		ret = getcon_raw(&con);
431 
432 		if (ret == -1)
433 			err(EXIT_FAILURE,
434 			    " Couldn't get current security context");
435 		break;
436 	case OPTS_FROM_CUREXE:
437 		ret = getexeccon_raw(&con);
438 
439 		if (ret == -1)
440 			err(EXIT_FAILURE,
441 			    " Couldn't get current exec security context");
442 
443 		if (!con)
444 			con = strdup(dummy_NIL);
445 		break;
446 	case OPTS_FROM_CURFS:
447 		ret = getfscreatecon_raw(&con);
448 
449 		if (ret == -1)
450 			err(EXIT_FAILURE,
451 			    " Couldn't get current fs security context");
452 
453 		if (!con)
454 			con = strdup(dummy_NIL);
455 		break;
456 	case OPTS_FROM_CURKEY:
457 		ret = getkeycreatecon_raw(&con);
458 
459 		if (ret == -1)
460 			err(EXIT_FAILURE,
461 			    " Couldn't get current key security context");
462 
463 		if (!con)
464 			con = strdup(dummy_NIL);
465 		break;
466 
467 	case OPTS_FROM_PROC:
468 		ret = getpidcon_raw(opts->f.pid, &con);
469 
470 		if (ret == -1)
471 			err(EXIT_FAILURE,
472 			    " Couldn't get security context for pid %lu",
473 			    (unsigned long)opts->f.pid);
474 		break;
475 	case OPTS_FROM_PROCEXE:
476 		ret = my_getpidexeccon_raw(opts->f.pid, &con);
477 
478 		if (ret == -1)
479 			err(EXIT_FAILURE,
480 			    " Couldn't get security context for pid %lu",
481 			    (unsigned long)opts->f.pid);
482 
483 		if (!con)
484 			con = strdup(dummy_NIL);
485 		break;
486 	case OPTS_FROM_PROCFS:
487 		ret = my_getpidfscreatecon_raw(opts->f.pid, &con);
488 
489 		if (ret == -1)
490 			err(EXIT_FAILURE,
491 			    " Couldn't get security context for pid %lu",
492 			    (unsigned long)opts->f.pid);
493 
494 		if (!con)
495 			con = strdup(dummy_NIL);
496 		/* disabled -- override with normal context ...
497 		   {
498 		   opts->from_type = OPTS_FROM_PROC;
499 		   return (get_scon());
500 		   } */
501 		break;
502 	case OPTS_FROM_PROCKEY:
503 		ret = my_getpidkeycreatecon_raw(opts->f.pid, &con);
504 
505 		if (ret == -1)
506 			err(EXIT_FAILURE,
507 			    " Couldn't get security context for pid %lu",
508 			    (unsigned long)opts->f.pid);
509 
510 		if (!con)
511 			con = strdup(dummy_NIL);
512 		break;
513 
514 	case OPTS_FROM_FILE:
515 		ret = getfilecon_raw(opts->f.file, &con);
516 
517 		if (ret == -1)
518 			err(EXIT_FAILURE,
519 			    " Couldn't get security context for file %s",
520 			    opts->f.file);
521 		break;
522 
523 	case OPTS_FROM_LINK:
524 		ret = lgetfilecon_raw(opts->f.link, &con);
525 
526 		if (ret == -1)
527 			err(EXIT_FAILURE,
528 			    " Couldn't get security context for symlink %s",
529 			    opts->f.link);
530 		break;
531 
532 	default:
533 		assert(FALSE);
534 	}
535 
536 	return (con);
537 }
538 
disp__color_to_ansi(const char * color_str)539 static unsigned int disp__color_to_ansi(const char *color_str)
540 {
541 	int val = 30;
542 
543 	/* NOTE: ansi black is 30 for foreground colors */
544 
545 	/* red */
546 	if (strncasecmp(&color_str[1], "7f", 2) >= 0)
547 		val += 1;
548 	/* green */
549 	if (strncasecmp(&color_str[3], "7f", 2) >= 0)
550 		val += 2;
551 	/* blue */
552 	if (strncasecmp(&color_str[5], "7f", 2) >= 0)
553 		val += 4;
554 
555 	return val;
556 }
557 
disp__con_color_ansi(const char * name,struct context_color_t * color)558 static char *disp__con_color_ansi(const char *name,
559 				  struct context_color_t *color)
560 {
561 	unsigned int fg, bg;
562 	char *ansi;
563 	int ansi_len = strlen("\e[99;99m") + 1;
564 
565 	/* NOTE: ansi background codes are the same as foreground codes +10 */
566 
567 	if (xstreq("user", name)) {
568 		fg = disp__color_to_ansi(color->user_fg);
569 		bg = disp__color_to_ansi(color->user_bg) + 10;
570 	} else if (xstreq("role", name)) {
571 		fg = disp__color_to_ansi(color->role_fg);
572 		bg = disp__color_to_ansi(color->role_bg) + 10;
573 	} else if (xstreq("type", name)) {
574 		fg = disp__color_to_ansi(color->type_fg);
575 		bg = disp__color_to_ansi(color->type_bg) + 10;
576 	} else if (xstreq("sensitivity", name) ||
577 		   xstreq("clearance", name) ||
578 		   xstreq("mls-range", name)) {
579 		fg = disp__color_to_ansi(color->range_fg);
580 		bg = disp__color_to_ansi(color->range_bg) + 10;
581 	} else
582 		err(EXIT_FAILURE, " No color information for context field");
583 
584 	if (!(ansi = malloc(ansi_len)))
585 		err(EXIT_FAILURE, " Unable to allocate memory");
586 	if (snprintf(ansi, ansi_len, "\e[%d;%dm", fg, bg) > ansi_len)
587 		err(EXIT_FAILURE, " Unable to convert colors to ANSI codes");
588 
589 	return ansi;
590 }
591 
disp__con_val(const char * name,const char * val,struct context_color_t * color)592 static void disp__con_val(const char *name, const char *val,
593 			  struct context_color_t *color)
594 {
595 	static int done = FALSE;
596 
597 	assert(name);
598 	assert(color);
599 
600 	if (!val)
601 		val = "";	/* targeted has no "level" etc.,
602 				   any errors should happen at context_new() time */
603 
604 	if (opts->disp_prompt) {
605 		if (xstreq("mls-range", name) && !*val)
606 			return;	/* skip, mls-range if it's empty */
607 
608 		if (opts->disp_color && color->valid) {
609 			char *ansi = disp__con_color_ansi(name, color);
610 			fprintf(stdout, "%s", ansi);
611 			free(ansi);
612 		}
613 		fprintf(stdout, "%s%s", done ? ":" : "", val);
614 		if (opts->disp_color && color->valid)
615 			fprintf(stdout, "\e[0m");
616 	} else if (disp_multi())
617 		fprintf(stdout, "%s: %s\n", name, val);
618 	else
619 		fprintf(stdout, "%s\n", val);
620 
621 	done = TRUE;
622 }
623 
disp_con(security_context_t scon_raw)624 static void disp_con(security_context_t scon_raw)
625 {
626 	security_context_t scon_trans, scon;
627 	context_t con = NULL;
628 	char *color_str = NULL;
629 	struct context_color_t color = { .valid = 0 };
630 
631 	selinux_raw_to_trans_context(scon_raw, &scon_trans);
632 	if (opts->disp_raw)
633 		scon = scon_raw;
634 	else
635 		scon = scon_trans;
636 
637 	if (!*scon) {		/* --self-exec and --self-fs etc. */
638 		if (opts->disp_user)
639 			disp__con_val("user", NULL, &color);
640 		if (opts->disp_role)
641 			disp__con_val("role", NULL, &color);
642 		if (opts->disp_type)
643 			disp__con_val("type", NULL, &color);
644 		if (opts->disp_sen)
645 			disp__con_val("sensitivity", NULL, &color);
646 		if (opts->disp_clr)
647 			disp__con_val("clearance", NULL, &color);
648 		if (opts->disp_mlsr)
649 			disp__con_val("mls-range", NULL, &color);
650 		return;
651 	}
652 
653 	if (opts->disp_color) {
654 		if (selinux_raw_context_to_color(scon_raw, &color_str) < 0)
655 			errx(EXIT_FAILURE, "Couldn't determine colors for: %s",
656 			     scon);
657 
658 		color.user_fg = strtok(color_str, " ");
659 		if (!color.user_fg)
660 			errx(EXIT_FAILURE, "Invalid color string");
661 		color.user_bg = strtok(NULL, " ");
662 		if (!color.user_bg)
663 			errx(EXIT_FAILURE, "Invalid color string");
664 
665 		color.role_fg = strtok(NULL, " ");
666 		if (!color.role_fg)
667 			errx(EXIT_FAILURE, "Invalid color string");
668 		color.role_bg = strtok(NULL, " ");
669 		if (!color.role_bg)
670 			errx(EXIT_FAILURE, "Invalid color string");
671 
672 		color.type_fg = strtok(NULL, " ");
673 		if (!color.type_fg)
674 			errx(EXIT_FAILURE, "Invalid color string");
675 		color.type_bg = strtok(NULL, " ");
676 		if (!color.type_bg)
677 			errx(EXIT_FAILURE, "Invalid color string");
678 
679 		color.range_fg = strtok(NULL, " ");
680 		if (!color.range_fg)
681 			errx(EXIT_FAILURE, "Invalid color string");
682 		color.range_bg = strtok(NULL, " ");
683 
684 		color.valid = 1;
685 	};
686 
687 	if (!(con = context_new(scon)))
688 		errx(EXIT_FAILURE, "Couldn't create context from: %s", scon);
689 
690 	if (opts->disp_user) {
691 		disp__con_val("user", context_user_get(con), &color);
692 	}
693 	if (opts->disp_role) {
694 		disp__con_val("role", context_role_get(con), &color);
695 	}
696 	if (opts->disp_type) {
697 		disp__con_val("type", context_type_get(con), &color);
698 	}
699 	if (opts->disp_sen) {
700 		const char *val = NULL;
701 		char *tmp = NULL;
702 
703 		val = context_range_get(con);
704 		if (!val)
705 			val = "";	/* targeted has no "level" etc.,
706 					   any errors should happen at context_new() time */
707 
708 		tmp = strdup(val);
709 		if (!tmp)
710 			errx(EXIT_FAILURE, "Couldn't create context from: %s",
711 			     scon);
712 		if (strchr(tmp, '-'))
713 			*strchr(tmp, '-') = 0;
714 
715 		disp__con_val("sensitivity", tmp, &color);
716 
717 		free(tmp);
718 	}
719 	if (opts->disp_clr) {
720 		const char *val = NULL;
721 		char *tmp = NULL;
722 
723 		val = context_range_get(con);
724 		if (!val)
725 			val = "";	/* targeted has no "level" etc.,
726 					   any errors should happen at context_new() time */
727 
728 		tmp = strdup(val);
729 		if (!tmp)
730 			errx(EXIT_FAILURE, "Couldn't create context from: %s",
731 			     scon);
732 		if (strchr(tmp, '-'))
733 			disp__con_val("clearance", strchr(tmp, '-') + 1, &color);
734 		else
735 			disp__con_val("clearance", tmp, &color);
736 
737 		free(tmp);
738 	}
739 
740 	if (opts->disp_mlsr)
741 		disp__con_val("mls-range", context_range_get(con), &color);
742 
743 	context_free(con);
744 	freecon(scon_trans);
745 	if (color_str)
746 		free(color_str);
747 }
748 
main(int argc,char * argv[])749 int main(int argc, char *argv[])
750 {
751 	security_context_t scon_raw = NULL;
752 
753 	cmd_line(argc, argv);
754 
755 	scon_raw = get_scon();
756 
757 	disp_con(scon_raw);
758 
759 	freecon(scon_raw);
760 
761 	exit(EXIT_SUCCESS);
762 }
763