16cd6a6acSopenharmony_ci#include <stdio.h>
26cd6a6acSopenharmony_ci#include <stdlib.h>
36cd6a6acSopenharmony_ci#include <string.h>
46cd6a6acSopenharmony_ci#include <getopt.h>
56cd6a6acSopenharmony_ci#include <errno.h>
66cd6a6acSopenharmony_ci#include <selinux/selinux.h>
76cd6a6acSopenharmony_ci#include <selinux/label.h>
86cd6a6acSopenharmony_ci
96cd6a6acSopenharmony_cistatic __attribute__ ((__noreturn__)) void usage(const char *progname)
106cd6a6acSopenharmony_ci{
116cd6a6acSopenharmony_ci	fprintf(stderr,
126cd6a6acSopenharmony_ci		"usage: %s -b backend [-v] [-r] -k key [-t type] [-f file]\n\n"
136cd6a6acSopenharmony_ci		"Where:\n\t"
146cd6a6acSopenharmony_ci		"-b  The backend - \"file\", \"media\", \"x\", \"db\" or "
156cd6a6acSopenharmony_ci			"\"prop\"\n\t"
166cd6a6acSopenharmony_ci		"-v  Validate entries against loaded policy.\n\t"
176cd6a6acSopenharmony_ci		"-r  Use \"raw\" function.\n\t"
186cd6a6acSopenharmony_ci		"-k  Lookup key - Depends on backend.\n\t"
196cd6a6acSopenharmony_ci		"-t  Lookup type - Optional as depends on backend.\n\t"
206cd6a6acSopenharmony_ci		"-f  Optional file containing the specs (defaults to\n\t"
216cd6a6acSopenharmony_ci		"    those used by loaded policy).\n\n"
226cd6a6acSopenharmony_ci		"Examples:\n\t"
236cd6a6acSopenharmony_ci		"%s -v -b file -k /run -t 0\n\t"
246cd6a6acSopenharmony_ci		"   lookup with validation against the loaded policy, the\n\t"
256cd6a6acSopenharmony_ci		"   \"file\" backend for path \"/run\" with mode = 0\n\t"
266cd6a6acSopenharmony_ci		"%s -r -b x -t 4 -k X11:ButtonPress\n\t"
276cd6a6acSopenharmony_ci		"   lookup_raw the \"X\" backend for type SELABEL_X_EVENT\n\t"
286cd6a6acSopenharmony_ci		"   using key \"X11:ButtonPress\"\n\n",
296cd6a6acSopenharmony_ci		progname, progname, progname);
306cd6a6acSopenharmony_ci	exit(1);
316cd6a6acSopenharmony_ci}
326cd6a6acSopenharmony_ci
336cd6a6acSopenharmony_ciint main(int argc, char **argv)
346cd6a6acSopenharmony_ci{
356cd6a6acSopenharmony_ci	int raw = 0, type = 0, backend = 0, rc, opt;
366cd6a6acSopenharmony_ci	char *validate = NULL, *key = NULL, *context = NULL, *file = NULL;
376cd6a6acSopenharmony_ci
386cd6a6acSopenharmony_ci	struct selabel_handle *hnd;
396cd6a6acSopenharmony_ci	struct selinux_opt selabel_option[] = {
406cd6a6acSopenharmony_ci		{ SELABEL_OPT_PATH, file },
416cd6a6acSopenharmony_ci		{ SELABEL_OPT_VALIDATE, validate }
426cd6a6acSopenharmony_ci	};
436cd6a6acSopenharmony_ci
446cd6a6acSopenharmony_ci	if (argc < 3)
456cd6a6acSopenharmony_ci		usage(argv[0]);
466cd6a6acSopenharmony_ci
476cd6a6acSopenharmony_ci	while ((opt = getopt(argc, argv, "b:f:vrk:t:")) > 0) {
486cd6a6acSopenharmony_ci		switch (opt) {
496cd6a6acSopenharmony_ci		case 'b':
506cd6a6acSopenharmony_ci			if (!strcasecmp(optarg, "file")) {
516cd6a6acSopenharmony_ci				backend = SELABEL_CTX_FILE;
526cd6a6acSopenharmony_ci			} else if (!strcmp(optarg, "media")) {
536cd6a6acSopenharmony_ci				backend = SELABEL_CTX_MEDIA;
546cd6a6acSopenharmony_ci			} else if (!strcmp(optarg, "x")) {
556cd6a6acSopenharmony_ci				backend = SELABEL_CTX_X;
566cd6a6acSopenharmony_ci			} else if (!strcmp(optarg, "db")) {
576cd6a6acSopenharmony_ci				backend = SELABEL_CTX_DB;
586cd6a6acSopenharmony_ci			} else if (!strcmp(optarg, "prop")) {
596cd6a6acSopenharmony_ci				backend = SELABEL_CTX_ANDROID_PROP;
606cd6a6acSopenharmony_ci			} else if (!strcmp(optarg, "service")) {
616cd6a6acSopenharmony_ci				backend = SELABEL_CTX_ANDROID_SERVICE;
626cd6a6acSopenharmony_ci			} else {
636cd6a6acSopenharmony_ci				fprintf(stderr, "Unknown backend: %s\n",
646cd6a6acSopenharmony_ci								    optarg);
656cd6a6acSopenharmony_ci				usage(argv[0]);
666cd6a6acSopenharmony_ci			}
676cd6a6acSopenharmony_ci			break;
686cd6a6acSopenharmony_ci		case 'f':
696cd6a6acSopenharmony_ci			file = optarg;
706cd6a6acSopenharmony_ci			break;
716cd6a6acSopenharmony_ci		case 'v':
726cd6a6acSopenharmony_ci			validate = (char *)1;
736cd6a6acSopenharmony_ci			break;
746cd6a6acSopenharmony_ci		case 'r':
756cd6a6acSopenharmony_ci			raw = 1;
766cd6a6acSopenharmony_ci			break;
776cd6a6acSopenharmony_ci		case 'k':
786cd6a6acSopenharmony_ci			key = optarg;
796cd6a6acSopenharmony_ci			break;
806cd6a6acSopenharmony_ci		case 't':
816cd6a6acSopenharmony_ci			type = atoi(optarg);
826cd6a6acSopenharmony_ci			break;
836cd6a6acSopenharmony_ci		default:
846cd6a6acSopenharmony_ci			usage(argv[0]);
856cd6a6acSopenharmony_ci		}
866cd6a6acSopenharmony_ci	}
876cd6a6acSopenharmony_ci
886cd6a6acSopenharmony_ci	selabel_option[0].value = file;
896cd6a6acSopenharmony_ci	selabel_option[1].value = validate;
906cd6a6acSopenharmony_ci
916cd6a6acSopenharmony_ci	hnd = selabel_open(backend, selabel_option, 2);
926cd6a6acSopenharmony_ci	if (!hnd) {
936cd6a6acSopenharmony_ci		fprintf(stderr, "ERROR: selabel_open - Could not obtain "
946cd6a6acSopenharmony_ci							     "handle:  %s\n",
956cd6a6acSopenharmony_ci							     strerror(errno));
966cd6a6acSopenharmony_ci		return -1;
976cd6a6acSopenharmony_ci	}
986cd6a6acSopenharmony_ci
996cd6a6acSopenharmony_ci	switch (raw) {
1006cd6a6acSopenharmony_ci	case 1:
1016cd6a6acSopenharmony_ci		rc = selabel_lookup_raw(hnd, &context, key, type);
1026cd6a6acSopenharmony_ci		break;
1036cd6a6acSopenharmony_ci	default:
1046cd6a6acSopenharmony_ci		rc = selabel_lookup(hnd, &context, key, type);
1056cd6a6acSopenharmony_ci	}
1066cd6a6acSopenharmony_ci	selabel_close(hnd);
1076cd6a6acSopenharmony_ci
1086cd6a6acSopenharmony_ci	if (rc) {
1096cd6a6acSopenharmony_ci		switch (errno) {
1106cd6a6acSopenharmony_ci		case ENOENT:
1116cd6a6acSopenharmony_ci			fprintf(stderr, "ERROR: selabel_lookup failed to "
1126cd6a6acSopenharmony_ci					    "find a valid context.\n");
1136cd6a6acSopenharmony_ci			break;
1146cd6a6acSopenharmony_ci		case EINVAL:
1156cd6a6acSopenharmony_ci			fprintf(stderr, "ERROR: selabel_lookup failed to "
1166cd6a6acSopenharmony_ci				    "validate context, or key / type are "
1176cd6a6acSopenharmony_ci				    "invalid.\n");
1186cd6a6acSopenharmony_ci			break;
1196cd6a6acSopenharmony_ci		default:
1206cd6a6acSopenharmony_ci			fprintf(stderr, "selabel_lookup ERROR: %s\n",
1216cd6a6acSopenharmony_ci						    strerror(errno));
1226cd6a6acSopenharmony_ci		}
1236cd6a6acSopenharmony_ci	} else {
1246cd6a6acSopenharmony_ci		printf("Default context: %s\n", context);
1256cd6a6acSopenharmony_ci		freecon(context);
1266cd6a6acSopenharmony_ci	}
1276cd6a6acSopenharmony_ci
1286cd6a6acSopenharmony_ci	return rc;
1296cd6a6acSopenharmony_ci}
130