• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 __attribute__((__noreturn__)) 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,      --self        Get the context for the current process.\n"
93 		"          --current-exec, --self-exec   Get the exec context for the current process.\n"
94 		"          --current-fs,   --self-fs     Get the fs context for the current process.\n"
95 		"          --current-key,  --self-key    Get the key context for the current process.\n"
96 		"          --parent                      Get the context for the parent process.\n"
97 		"          --parent-exec                 Get the exec context for the parent process.\n"
98 		"          --parent-fs                   Get the fs context for the parent process.\n"
99 		"          --parent-key                  Get the key context for the parent process.\n"
100 		"          --pid           -p <arg>      Use the context from the specified pid.\n"
101 		"          --pid-exec      <arg>         Use the exec context from the specified pid.\n"
102 		"          --pid-fs        <arg>         Use the fs context from the specified pid.\n"
103 		"          --pid-key       <arg>         Use the key context from the specified pid.\n"
104 		"          --file          -f <arg>      Use the context from the specified file.\n"
105 		"          --link          -L <arg>      Use the context from the specified link.\n",
106 		name, SECON_OPTS_SM);
107 
108 	exit(exit_code);
109 }
110 
opt_program_name(const char * argv0,const char * def)111 static const char *opt_program_name(const char *argv0, const char *def)
112 {
113 	if (argv0) {
114 		if ((def = strrchr(argv0, '/')))
115 			++def;
116 		else
117 			def = argv0;
118 
119 		/* hack for libtool */
120 		if ((strlen(def) > strlen("lt-"))
121 		    && !memcmp("lt-", def, strlen("lt-")))
122 			def += 3;
123 	}
124 
125 	return (def);
126 }
127 
disp_num(void)128 static int disp_num(void)
129 {
130 	int num = 0;
131 
132 	num += opts->disp_user;
133 	num += opts->disp_role;
134 	num += opts->disp_type;
135 	num += opts->disp_sen;
136 	num += opts->disp_clr;
137 	num += opts->disp_mlsr;
138 
139 	return (num);
140 }
141 
disp_none(void)142 static int disp_none(void)
143 {
144 	return (!disp_num());
145 }
146 
disp_multi(void)147 static int disp_multi(void)
148 {
149 	return (disp_num() > 1);
150 }
151 
cmd_line(int argc,char * argv[])152 static void cmd_line(int argc, char *argv[])
153 {
154 	int optchar = 0;
155 	const char *program_name = NULL;
156 	struct option long_options[] = {
157 		{"help", no_argument, NULL, 'h'},
158 		{"version", no_argument, NULL, 'V'},
159 
160 		{"prompt", no_argument, NULL, 'P'},
161 
162 		{"user", no_argument, NULL, 'u'},
163 		{"role", no_argument, NULL, 'r'},
164 		{"type", no_argument, NULL, 't'},
165 		{"level", no_argument, NULL, 'l'},	/* compat. */
166 		{"sensitivity", no_argument, NULL, 's'},
167 		{"range", no_argument, NULL, 'm'},
168 		{"clearance", no_argument, NULL, 'c'},
169 		{"mls-range", no_argument, NULL, 'm'},
170 
171 		{"raw", no_argument, NULL, 'R'},
172 		{"color", no_argument, NULL, 'C'},
173 
174 		{"current", no_argument, NULL, 1},
175 		{"self", no_argument, NULL, 1},
176 		{"current-exec", no_argument, NULL, 2},
177 		{"self-exec", no_argument, NULL, 2},
178 		{"current-fs", no_argument, NULL, 3},
179 		{"self-fs", no_argument, NULL, 3},
180 		{"current-key", no_argument, NULL, 4},
181 		{"self-key", no_argument, NULL, 4},
182 
183 		{"parent", no_argument, NULL, 5},
184 		{"parent-exec", no_argument, NULL, 6},
185 		{"parent-fs", no_argument, NULL, 7},
186 		{"parent-key", no_argument, NULL, 8},
187 
188 		{"file", required_argument, NULL, 'f'},
189 		{"link", required_argument, NULL, 'L'},
190 		{"pid", required_argument, NULL, 'p'},
191 		{"pid-exec", required_argument, NULL, 9},
192 		{"pid-fs", required_argument, NULL, 10},
193 		{"pid-key", required_argument, NULL, 11},
194 
195 		{NULL, 0, NULL, 0}
196 	};
197 	int done = FALSE;
198 
199 	program_name = opt_program_name(argv[0], SECON_CONF_PROG_NAME);
200 
201 	while ((optchar = getopt_long(argc, argv, SECON_OPTS_GO,
202 				      long_options, NULL)) != -1) {
203 		switch (optchar) {
204 		case '?':
205 			usage(program_name, EXIT_FAILURE);
206 		case 'h':
207 			usage(program_name, EXIT_SUCCESS);
208 		case 'V':
209 			fprintf(stdout,
210 				" %s version %s.\n", program_name, VERSION);
211 			exit(EXIT_SUCCESS);
212 
213 		case 'u':
214 			done = TRUE;
215 			opts->disp_user = !opts->disp_user;
216 			break;
217 		case 'r':
218 			done = TRUE;
219 			opts->disp_role = !opts->disp_role;
220 			break;
221 		case 't':
222 			done = TRUE;
223 			opts->disp_type = !opts->disp_type;
224 			break;
225 		case 'l':
226 			done = TRUE;
227 			opts->disp_sen = !opts->disp_sen;
228 			break;
229 		case 's':
230 			done = TRUE;
231 			opts->disp_sen = !opts->disp_sen;
232 			break;
233 		case 'c':
234 			done = TRUE;
235 			opts->disp_clr = !opts->disp_clr;
236 			break;
237 		case 'm':
238 			done = TRUE;
239 			opts->disp_mlsr = !opts->disp_mlsr;
240 			break;
241 
242 		case 'P':
243 			opts->disp_prompt = !opts->disp_prompt;
244 			break;
245 
246 		case 'R':
247 			opts->disp_raw = !opts->disp_raw;
248 			break;
249 		case 'C':
250 			opts->disp_color = !opts->disp_color;
251 			break;
252 		case 1:
253 			opts->from_type = OPTS_FROM_CUR;
254 			break;
255 		case 2:
256 			opts->from_type = OPTS_FROM_CUREXE;
257 			break;
258 		case 3:
259 			opts->from_type = OPTS_FROM_CURFS;
260 			break;
261 		case 4:
262 			opts->from_type = OPTS_FROM_CURKEY;
263 			break;
264 
265 		case 5:
266 			opts->from_type = OPTS_FROM_PROC;
267 			opts->f.pid = getppid();
268 			break;
269 		case 6:
270 			opts->from_type = OPTS_FROM_PROCEXE;
271 			opts->f.pid = getppid();
272 			break;
273 		case 7:
274 			opts->from_type = OPTS_FROM_PROCFS;
275 			opts->f.pid = getppid();
276 			break;
277 		case 8:
278 			opts->from_type = OPTS_FROM_PROCKEY;
279 			opts->f.pid = getppid();
280 			break;
281 
282 		case 'f':
283 			opts->from_type = OPTS_FROM_FILE;
284 			opts->f.file = optarg;
285 			break;
286 		case 'L':
287 			opts->from_type = OPTS_FROM_LINK;
288 			opts->f.link = optarg;
289 			break;
290 		case 'p':
291 			opts->from_type = OPTS_FROM_PROC;
292 			opts->f.pid = atoi(optarg);
293 			break;
294 		case 9:
295 			opts->from_type = OPTS_FROM_PROCEXE;
296 			opts->f.pid = atoi(optarg);
297 			break;
298 		case 10:
299 			opts->from_type = OPTS_FROM_PROCFS;
300 			opts->f.pid = atoi(optarg);
301 			break;
302 		case 11:
303 			opts->from_type = OPTS_FROM_PROCKEY;
304 			opts->f.pid = atoi(optarg);
305 			break;
306 
307 		default:
308 			assert(FALSE);
309 		}
310 	}
311 
312 	if (!done) {		/* default, if nothing specified */
313 		opts->disp_user = TRUE;
314 		opts->disp_role = TRUE;
315 		opts->disp_type = TRUE;
316 		if (!opts->disp_prompt) {	/* when displaying prompt, just output "normal" by default */
317 			opts->disp_sen = TRUE;
318 			opts->disp_clr = TRUE;
319 		}
320 		opts->disp_mlsr = TRUE;
321 	}
322 
323 	if (disp_none())
324 		err(EXIT_FAILURE, " Nothing to display");
325 
326 	argc -= optind;
327 	argv += optind;
328 
329 	if (!argc && (opts->from_type == OPTS_FROM_ARG)
330 	    && !isatty(STDIN_FILENO))
331 		opts->from_type = OPTS_FROM_STDIN;
332 	if (!argc && (opts->from_type == OPTS_FROM_ARG))
333 		opts->from_type = OPTS_FROM_CUR;
334 
335 	if (opts->from_type == OPTS_FROM_ARG) {
336 		opts->f.arg = argv[0];
337 
338 		if (xstreq(argv[0], "-"))
339 			opts->from_type = OPTS_FROM_STDIN;
340 	} else if (!is_selinux_enabled())
341 		errx(EXIT_FAILURE, "SELinux is not enabled");
342 }
343 
my_getXcon_raw(pid_t pid,security_context_t * con,const char * val)344 static int my_getXcon_raw(pid_t pid, security_context_t * con, const char *val)
345 {
346 	char buf[4096];
347 	FILE *fp = NULL;
348 	const char *ptr = NULL;
349 
350 	snprintf(buf, sizeof(buf), "%s/%ld/attr/%s", "/proc", (long int)pid,
351 		 val);
352 
353 	if (!(fp = fopen(buf, "rb")))
354 		return (-1);
355 
356 	ptr = fgets(buf, sizeof(buf), fp);
357 
358 	fclose(fp);
359 
360 	*con = NULL;
361 	if (ptr) {		/* return *con = NULL, when proc file is empty */
362 		char *tmp = strchr(ptr, '\n');
363 
364 		if (tmp)
365 			*tmp = 0;
366 
367 		if (*ptr && !(*con = strdup(ptr)))
368 			return (-1);
369 	}
370 
371 	return (0);
372 }
373 
my_getpidexeccon_raw(pid_t pid,security_context_t * con)374 static int my_getpidexeccon_raw(pid_t pid, security_context_t * con)
375 {
376 	return (my_getXcon_raw(pid, con, "exec"));
377 }
my_getpidfscreatecon_raw(pid_t pid,security_context_t * con)378 static int my_getpidfscreatecon_raw(pid_t pid, security_context_t * con)
379 {
380 	return (my_getXcon_raw(pid, con, "fscreate"));
381 }
my_getpidkeycreatecon_raw(pid_t pid,security_context_t * con)382 static int my_getpidkeycreatecon_raw(pid_t pid, security_context_t * con)
383 {
384 	return (my_getXcon_raw(pid, con, "keycreate"));
385 }
386 
get_scon(void)387 static security_context_t get_scon(void)
388 {
389 	static char dummy_NIL[1] = "";
390 	security_context_t con = NULL, con_tmp;
391 	int ret = -1;
392 
393 	switch (opts->from_type) {
394 	case OPTS_FROM_ARG:
395 		if (!(con_tmp = strdup(opts->f.arg)))
396 			err(EXIT_FAILURE,
397 			    " Couldn't allocate security context");
398 		if (selinux_trans_to_raw_context(con_tmp, &con) < 0)
399 			err(EXIT_FAILURE,
400 			    " Couldn't translate security context");
401 		freecon(con_tmp);
402 		break;
403 
404 	case OPTS_FROM_STDIN:
405 		{
406 			char buf[4096] = "";
407 			char *ptr = buf;
408 
409 			while (!*ptr) {
410 				if (!(ptr = fgets(buf, sizeof(buf), stdin)))
411 					err(EXIT_FAILURE,
412 					    " Couldn't read security context");
413 
414 				ptr += strspn(ptr, " \n\t");
415 				ptr[strcspn(ptr, " \n\t")] = 0;
416 			}
417 
418 			if (!(con_tmp = strdup(ptr)))
419 				err(EXIT_FAILURE,
420 				    " Couldn't allocate security context");
421 			if (selinux_trans_to_raw_context(con_tmp, &con) < 0)
422 				err(EXIT_FAILURE,
423 				    " Couldn't translate security context");
424 			freecon(con_tmp);
425 			break;
426 		}
427 
428 	case OPTS_FROM_CUR:
429 		ret = getcon_raw(&con);
430 
431 		if (ret == -1)
432 			err(EXIT_FAILURE,
433 			    " Couldn't get current security context");
434 		break;
435 	case OPTS_FROM_CUREXE:
436 		ret = getexeccon_raw(&con);
437 
438 		if (ret == -1)
439 			err(EXIT_FAILURE,
440 			    " Couldn't get current exec security context");
441 
442 		if (!con)
443 			con = strdup(dummy_NIL);
444 		break;
445 	case OPTS_FROM_CURFS:
446 		ret = getfscreatecon_raw(&con);
447 
448 		if (ret == -1)
449 			err(EXIT_FAILURE,
450 			    " Couldn't get current fs security context");
451 
452 		if (!con)
453 			con = strdup(dummy_NIL);
454 		break;
455 	case OPTS_FROM_CURKEY:
456 		ret = getkeycreatecon_raw(&con);
457 
458 		if (ret == -1)
459 			err(EXIT_FAILURE,
460 			    " Couldn't get current key security context");
461 
462 		if (!con)
463 			con = strdup(dummy_NIL);
464 		break;
465 
466 	case OPTS_FROM_PROC:
467 		ret = getpidcon_raw(opts->f.pid, &con);
468 
469 		if (ret == -1)
470 			err(EXIT_FAILURE,
471 			    " Couldn't get security context for pid %lu",
472 			    (unsigned long)opts->f.pid);
473 		break;
474 	case OPTS_FROM_PROCEXE:
475 		ret = my_getpidexeccon_raw(opts->f.pid, &con);
476 
477 		if (ret == -1)
478 			err(EXIT_FAILURE,
479 			    " Couldn't get security context for pid %lu",
480 			    (unsigned long)opts->f.pid);
481 
482 		if (!con)
483 			con = strdup(dummy_NIL);
484 		break;
485 	case OPTS_FROM_PROCFS:
486 		ret = my_getpidfscreatecon_raw(opts->f.pid, &con);
487 
488 		if (ret == -1)
489 			err(EXIT_FAILURE,
490 			    " Couldn't get security context for pid %lu",
491 			    (unsigned long)opts->f.pid);
492 
493 		if (!con)
494 			con = strdup(dummy_NIL);
495 		/* disabled -- override with normal context ...
496 		   {
497 		   opts->from_type = OPTS_FROM_PROC;
498 		   return (get_scon());
499 		   } */
500 		break;
501 	case OPTS_FROM_PROCKEY:
502 		ret = my_getpidkeycreatecon_raw(opts->f.pid, &con);
503 
504 		if (ret == -1)
505 			err(EXIT_FAILURE,
506 			    " Couldn't get security context for pid %lu",
507 			    (unsigned long)opts->f.pid);
508 
509 		if (!con)
510 			con = strdup(dummy_NIL);
511 		break;
512 
513 	case OPTS_FROM_FILE:
514 		ret = getfilecon_raw(opts->f.file, &con);
515 
516 		if (ret == -1)
517 			err(EXIT_FAILURE,
518 			    " Couldn't get security context for file %s",
519 			    opts->f.file);
520 		break;
521 
522 	case OPTS_FROM_LINK:
523 		ret = lgetfilecon_raw(opts->f.link, &con);
524 
525 		if (ret == -1)
526 			err(EXIT_FAILURE,
527 			    " Couldn't get security context for symlink %s",
528 			    opts->f.link);
529 		break;
530 
531 	default:
532 		assert(FALSE);
533 	}
534 
535 	return (con);
536 }
537 
disp__color_to_ansi(const char * color_str)538 static unsigned int disp__color_to_ansi(const char *color_str)
539 {
540 	int val = 30;
541 
542 	/* NOTE: ansi black is 30 for foreground colors */
543 
544 	/* red */
545 	if (strncasecmp(&color_str[1], "7f", 2) >= 0)
546 		val += 1;
547 	/* green */
548 	if (strncasecmp(&color_str[3], "7f", 2) >= 0)
549 		val += 2;
550 	/* blue */
551 	if (strncasecmp(&color_str[5], "7f", 2) >= 0)
552 		val += 4;
553 
554 	return val;
555 }
556 
disp__con_color_ansi(const char * name,struct context_color_t * color)557 static char *disp__con_color_ansi(const char *name,
558 				  struct context_color_t *color)
559 {
560 	unsigned int fg, bg;
561 	char *ansi;
562 	int ansi_len = strlen("\e[99;99m") + 1;
563 
564 	/* NOTE: ansi background codes are the same as foreground codes +10 */
565 
566 	if (xstreq("user", name)) {
567 		fg = disp__color_to_ansi(color->user_fg);
568 		bg = disp__color_to_ansi(color->user_bg) + 10;
569 	} else if (xstreq("role", name)) {
570 		fg = disp__color_to_ansi(color->role_fg);
571 		bg = disp__color_to_ansi(color->role_bg) + 10;
572 	} else if (xstreq("type", name)) {
573 		fg = disp__color_to_ansi(color->type_fg);
574 		bg = disp__color_to_ansi(color->type_bg) + 10;
575 	} else if (xstreq("sensitivity", name) ||
576 		   xstreq("clearance", name) ||
577 		   xstreq("mls-range", name)) {
578 		fg = disp__color_to_ansi(color->range_fg);
579 		bg = disp__color_to_ansi(color->range_bg) + 10;
580 	} else
581 		err(EXIT_FAILURE, " No color information for context field");
582 
583 	if (!(ansi = malloc(ansi_len)))
584 		err(EXIT_FAILURE, " Unable to allocate memory");
585 	if (snprintf(ansi, ansi_len, "\e[%d;%dm", fg, bg) > ansi_len)
586 		err(EXIT_FAILURE, " Unable to convert colors to ANSI codes");
587 
588 	return ansi;
589 }
590 
disp__con_val(const char * name,const char * val,struct context_color_t * color)591 static void disp__con_val(const char *name, const char *val,
592 			  struct context_color_t *color)
593 {
594 	static int done = FALSE;
595 
596 	assert(name);
597 	assert(color);
598 
599 	if (!val)
600 		val = "";	/* targeted has no "level" etc.,
601 				   any errors should happen at context_new() time */
602 
603 	if (opts->disp_prompt) {
604 		if (xstreq("mls-range", name) && !*val)
605 			return;	/* skip, mls-range if it's empty */
606 
607 		if (opts->disp_color && color->valid) {
608 			char *ansi = disp__con_color_ansi(name, color);
609 			fprintf(stdout, "%s", ansi);
610 			free(ansi);
611 		}
612 		fprintf(stdout, "%s%s", done ? ":" : "", val);
613 		if (opts->disp_color && color->valid)
614 			fprintf(stdout, "\e[0m");
615 	} else if (disp_multi())
616 		fprintf(stdout, "%s: %s\n", name, val);
617 	else
618 		fprintf(stdout, "%s\n", val);
619 
620 	done = TRUE;
621 }
622 
disp_con(security_context_t scon_raw)623 static void disp_con(security_context_t scon_raw)
624 {
625 	security_context_t scon_trans, scon;
626 	context_t con = NULL;
627 	char *color_str = NULL;
628 	struct context_color_t color = { .valid = 0 };
629 
630 	selinux_raw_to_trans_context(scon_raw, &scon_trans);
631 	if (opts->disp_raw)
632 		scon = scon_raw;
633 	else
634 		scon = scon_trans;
635 
636 	if (!*scon) {		/* --self-exec and --self-fs etc. */
637 		if (opts->disp_user)
638 			disp__con_val("user", NULL, &color);
639 		if (opts->disp_role)
640 			disp__con_val("role", NULL, &color);
641 		if (opts->disp_type)
642 			disp__con_val("type", NULL, &color);
643 		if (opts->disp_sen)
644 			disp__con_val("sensitivity", NULL, &color);
645 		if (opts->disp_clr)
646 			disp__con_val("clearance", NULL, &color);
647 		if (opts->disp_mlsr)
648 			disp__con_val("mls-range", NULL, &color);
649 		freecon(scon_trans);
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