1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <getopt.h>
5#include <errno.h>
6#include <selinux/selinux.h>
7#include <selinux/label.h>
8
9static __attribute__ ((__noreturn__)) void usage(const char *progname)
10{
11	fprintf(stderr,
12		"usage: %s -b backend [-v] [-r] -k key [-t type] [-f file]\n\n"
13		"Where:\n\t"
14		"-b  The backend - \"file\", \"media\", \"x\", \"db\" or "
15			"\"prop\"\n\t"
16		"-v  Validate entries against loaded policy.\n\t"
17		"-r  Use \"raw\" function.\n\t"
18		"-k  Lookup key - Depends on backend.\n\t"
19		"-t  Lookup type - Optional as depends on backend.\n\t"
20		"-f  Optional file containing the specs (defaults to\n\t"
21		"    those used by loaded policy).\n\n"
22		"Examples:\n\t"
23		"%s -v -b file -k /run -t 0\n\t"
24		"   lookup with validation against the loaded policy, the\n\t"
25		"   \"file\" backend for path \"/run\" with mode = 0\n\t"
26		"%s -r -b x -t 4 -k X11:ButtonPress\n\t"
27		"   lookup_raw the \"X\" backend for type SELABEL_X_EVENT\n\t"
28		"   using key \"X11:ButtonPress\"\n\n",
29		progname, progname, progname);
30	exit(1);
31}
32
33int main(int argc, char **argv)
34{
35	int raw = 0, type = 0, backend = 0, rc, opt;
36	char *validate = NULL, *key = NULL, *context = NULL, *file = NULL;
37
38	struct selabel_handle *hnd;
39	struct selinux_opt selabel_option[] = {
40		{ SELABEL_OPT_PATH, file },
41		{ SELABEL_OPT_VALIDATE, validate }
42	};
43
44	if (argc < 3)
45		usage(argv[0]);
46
47	while ((opt = getopt(argc, argv, "b:f:vrk:t:")) > 0) {
48		switch (opt) {
49		case 'b':
50			if (!strcasecmp(optarg, "file")) {
51				backend = SELABEL_CTX_FILE;
52			} else if (!strcmp(optarg, "media")) {
53				backend = SELABEL_CTX_MEDIA;
54			} else if (!strcmp(optarg, "x")) {
55				backend = SELABEL_CTX_X;
56			} else if (!strcmp(optarg, "db")) {
57				backend = SELABEL_CTX_DB;
58			} else if (!strcmp(optarg, "prop")) {
59				backend = SELABEL_CTX_ANDROID_PROP;
60			} else if (!strcmp(optarg, "service")) {
61				backend = SELABEL_CTX_ANDROID_SERVICE;
62			} else {
63				fprintf(stderr, "Unknown backend: %s\n",
64								    optarg);
65				usage(argv[0]);
66			}
67			break;
68		case 'f':
69			file = optarg;
70			break;
71		case 'v':
72			validate = (char *)1;
73			break;
74		case 'r':
75			raw = 1;
76			break;
77		case 'k':
78			key = optarg;
79			break;
80		case 't':
81			type = atoi(optarg);
82			break;
83		default:
84			usage(argv[0]);
85		}
86	}
87
88	selabel_option[0].value = file;
89	selabel_option[1].value = validate;
90
91	hnd = selabel_open(backend, selabel_option, 2);
92	if (!hnd) {
93		fprintf(stderr, "ERROR: selabel_open - Could not obtain "
94							     "handle:  %s\n",
95							     strerror(errno));
96		return -1;
97	}
98
99	switch (raw) {
100	case 1:
101		rc = selabel_lookup_raw(hnd, &context, key, type);
102		break;
103	default:
104		rc = selabel_lookup(hnd, &context, key, type);
105	}
106	selabel_close(hnd);
107
108	if (rc) {
109		switch (errno) {
110		case ENOENT:
111			fprintf(stderr, "ERROR: selabel_lookup failed to "
112					    "find a valid context.\n");
113			break;
114		case EINVAL:
115			fprintf(stderr, "ERROR: selabel_lookup failed to "
116				    "validate context, or key / type are "
117				    "invalid.\n");
118			break;
119		default:
120			fprintf(stderr, "selabel_lookup ERROR: %s\n",
121						    strerror(errno));
122		}
123	} else {
124		printf("Default context: %s\n", context);
125		freecon(context);
126	}
127
128	return rc;
129}
130