Home | History | Annotate | Download | only in secon
      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 
     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 
    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 
    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 
    142 static int disp_none(void)
    143 {
    144 	return (!disp_num());
    145 }
    146 
    147 static int disp_multi(void)
    148 {
    149 	return (disp_num() > 1);
    150 }
    151 
    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 
    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 
    374 static int my_getpidexeccon_raw(pid_t pid, security_context_t * con)
    375 {
    376 	return (my_getXcon_raw(pid, con, "exec"));
    377 }
    378 static int my_getpidfscreatecon_raw(pid_t pid, security_context_t * con)
    379 {
    380 	return (my_getXcon_raw(pid, con, "fscreate"));
    381 }
    382 static int my_getpidkeycreatecon_raw(pid_t pid, security_context_t * con)
    383 {
    384 	return (my_getXcon_raw(pid, con, "keycreate"));
    385 }
    386 
    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 
    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 
    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 
    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 
    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 
    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