xref: /aosp_15_r20/external/selinux/libselinux/src/audit2why.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /* Workaround for http://bugs.python.org/issue4835 */
2*2d543d20SAndroid Build Coastguard Worker #ifndef SIZEOF_SOCKET_T
3*2d543d20SAndroid Build Coastguard Worker #define SIZEOF_SOCKET_T SIZEOF_INT
4*2d543d20SAndroid Build Coastguard Worker #endif
5*2d543d20SAndroid Build Coastguard Worker 
6*2d543d20SAndroid Build Coastguard Worker #include <Python.h>
7*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
8*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
9*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
10*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
11*2d543d20SAndroid Build Coastguard Worker #include <getopt.h>
12*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
13*2d543d20SAndroid Build Coastguard Worker #include <sepol/sepol.h>
14*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb.h>
15*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/services.h>
16*2d543d20SAndroid Build Coastguard Worker #include <selinux/selinux.h>
17*2d543d20SAndroid Build Coastguard Worker 
18*2d543d20SAndroid Build Coastguard Worker #define UNKNOWN -1
19*2d543d20SAndroid Build Coastguard Worker #define BADSCON -2
20*2d543d20SAndroid Build Coastguard Worker #define BADTCON -3
21*2d543d20SAndroid Build Coastguard Worker #define BADTCLASS -4
22*2d543d20SAndroid Build Coastguard Worker #define BADPERM -5
23*2d543d20SAndroid Build Coastguard Worker #define BADCOMPUTE -6
24*2d543d20SAndroid Build Coastguard Worker #define NOPOLICY -7
25*2d543d20SAndroid Build Coastguard Worker #define ALLOW 0
26*2d543d20SAndroid Build Coastguard Worker #define DONTAUDIT 1
27*2d543d20SAndroid Build Coastguard Worker #define TERULE 2
28*2d543d20SAndroid Build Coastguard Worker #define BOOLEAN 3
29*2d543d20SAndroid Build Coastguard Worker #define CONSTRAINT 4
30*2d543d20SAndroid Build Coastguard Worker #define RBAC 5
31*2d543d20SAndroid Build Coastguard Worker #define BOUNDS 6
32*2d543d20SAndroid Build Coastguard Worker 
33*2d543d20SAndroid Build Coastguard Worker struct boolean_t {
34*2d543d20SAndroid Build Coastguard Worker 	char *name;
35*2d543d20SAndroid Build Coastguard Worker 	int active;
36*2d543d20SAndroid Build Coastguard Worker };
37*2d543d20SAndroid Build Coastguard Worker 
38*2d543d20SAndroid Build Coastguard Worker static struct boolean_t **boollist = NULL;
39*2d543d20SAndroid Build Coastguard Worker static int boolcnt = 0;
40*2d543d20SAndroid Build Coastguard Worker 
41*2d543d20SAndroid Build Coastguard Worker struct avc_t {
42*2d543d20SAndroid Build Coastguard Worker 	sepol_handle_t *handle;
43*2d543d20SAndroid Build Coastguard Worker 	sepol_policydb_t *policydb;
44*2d543d20SAndroid Build Coastguard Worker 	sepol_security_id_t ssid;
45*2d543d20SAndroid Build Coastguard Worker 	sepol_security_id_t tsid;
46*2d543d20SAndroid Build Coastguard Worker 	sepol_security_class_t tclass;
47*2d543d20SAndroid Build Coastguard Worker 	sepol_access_vector_t av;
48*2d543d20SAndroid Build Coastguard Worker };
49*2d543d20SAndroid Build Coastguard Worker 
50*2d543d20SAndroid Build Coastguard Worker static struct avc_t *avc = NULL;
51*2d543d20SAndroid Build Coastguard Worker 
52*2d543d20SAndroid Build Coastguard Worker static sidtab_t sidtab;
53*2d543d20SAndroid Build Coastguard Worker 
load_booleans(const sepol_bool_t * boolean,void * arg)54*2d543d20SAndroid Build Coastguard Worker static int load_booleans(const sepol_bool_t * boolean,
55*2d543d20SAndroid Build Coastguard Worker 			 void *arg __attribute__ ((__unused__)))
56*2d543d20SAndroid Build Coastguard Worker {
57*2d543d20SAndroid Build Coastguard Worker 	boollist[boolcnt] = malloc(sizeof(struct boolean_t));
58*2d543d20SAndroid Build Coastguard Worker 	boollist[boolcnt]->name = strdup(sepol_bool_get_name(boolean));
59*2d543d20SAndroid Build Coastguard Worker 	boollist[boolcnt]->active = sepol_bool_get_value(boolean);
60*2d543d20SAndroid Build Coastguard Worker 	boolcnt++;
61*2d543d20SAndroid Build Coastguard Worker 	return 0;
62*2d543d20SAndroid Build Coastguard Worker }
63*2d543d20SAndroid Build Coastguard Worker 
check_booleans(struct boolean_t ** bools)64*2d543d20SAndroid Build Coastguard Worker static int check_booleans(struct boolean_t **bools)
65*2d543d20SAndroid Build Coastguard Worker {
66*2d543d20SAndroid Build Coastguard Worker 	char errormsg[PATH_MAX];
67*2d543d20SAndroid Build Coastguard Worker 	struct sepol_av_decision avd;
68*2d543d20SAndroid Build Coastguard Worker 	unsigned int reason;
69*2d543d20SAndroid Build Coastguard Worker 	int rc;
70*2d543d20SAndroid Build Coastguard Worker 	int i;
71*2d543d20SAndroid Build Coastguard Worker 	sepol_bool_key_t *key = NULL;
72*2d543d20SAndroid Build Coastguard Worker 	sepol_bool_t *boolean = NULL;
73*2d543d20SAndroid Build Coastguard Worker 	int fcnt = 0;
74*2d543d20SAndroid Build Coastguard Worker 	int *foundlist = calloc(boolcnt, sizeof(int));
75*2d543d20SAndroid Build Coastguard Worker 	if (!foundlist) {
76*2d543d20SAndroid Build Coastguard Worker 		PyErr_SetString( PyExc_MemoryError, "Out of memory\n");
77*2d543d20SAndroid Build Coastguard Worker 		return fcnt;
78*2d543d20SAndroid Build Coastguard Worker 	}
79*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < boolcnt; i++) {
80*2d543d20SAndroid Build Coastguard Worker 		char *name = boollist[i]->name;
81*2d543d20SAndroid Build Coastguard Worker 		int active = boollist[i]->active;
82*2d543d20SAndroid Build Coastguard Worker 		rc = sepol_bool_key_create(avc->handle, name, &key);
83*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
84*2d543d20SAndroid Build Coastguard Worker 			PyErr_SetString( PyExc_RuntimeError,
85*2d543d20SAndroid Build Coastguard Worker 					 "Could not create boolean key.\n");
86*2d543d20SAndroid Build Coastguard Worker 			break;
87*2d543d20SAndroid Build Coastguard Worker 		}
88*2d543d20SAndroid Build Coastguard Worker 		rc = sepol_bool_query(avc->handle,
89*2d543d20SAndroid Build Coastguard Worker 				      avc->policydb,
90*2d543d20SAndroid Build Coastguard Worker 				      key, &boolean);
91*2d543d20SAndroid Build Coastguard Worker 
92*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
93*2d543d20SAndroid Build Coastguard Worker 			snprintf(errormsg, sizeof(errormsg),
94*2d543d20SAndroid Build Coastguard Worker 				 "Could not find boolean %s.\n", name);
95*2d543d20SAndroid Build Coastguard Worker 			PyErr_SetString( PyExc_RuntimeError, errormsg);
96*2d543d20SAndroid Build Coastguard Worker 			break;
97*2d543d20SAndroid Build Coastguard Worker 		}
98*2d543d20SAndroid Build Coastguard Worker 
99*2d543d20SAndroid Build Coastguard Worker 		sepol_bool_set_value(boolean, !active);
100*2d543d20SAndroid Build Coastguard Worker 
101*2d543d20SAndroid Build Coastguard Worker 		rc = sepol_bool_set(avc->handle,
102*2d543d20SAndroid Build Coastguard Worker 				    avc->policydb,
103*2d543d20SAndroid Build Coastguard Worker 				    key, boolean);
104*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
105*2d543d20SAndroid Build Coastguard Worker 			snprintf(errormsg, sizeof(errormsg),
106*2d543d20SAndroid Build Coastguard Worker 				 "Could not set boolean data %s.\n", name);
107*2d543d20SAndroid Build Coastguard Worker 			PyErr_SetString( PyExc_RuntimeError, errormsg);
108*2d543d20SAndroid Build Coastguard Worker 			break;
109*2d543d20SAndroid Build Coastguard Worker 		}
110*2d543d20SAndroid Build Coastguard Worker 
111*2d543d20SAndroid Build Coastguard Worker 		/* Reproduce the computation. */
112*2d543d20SAndroid Build Coastguard Worker 		rc = sepol_compute_av_reason(avc->ssid, avc->tsid, avc->tclass,
113*2d543d20SAndroid Build Coastguard Worker 					     avc->av, &avd, &reason);
114*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
115*2d543d20SAndroid Build Coastguard Worker 			snprintf(errormsg, sizeof(errormsg),
116*2d543d20SAndroid Build Coastguard Worker 				 "Error during access vector computation, skipping...");
117*2d543d20SAndroid Build Coastguard Worker 			PyErr_SetString( PyExc_RuntimeError, errormsg);
118*2d543d20SAndroid Build Coastguard Worker 
119*2d543d20SAndroid Build Coastguard Worker 			sepol_bool_free(boolean);
120*2d543d20SAndroid Build Coastguard Worker 			break;
121*2d543d20SAndroid Build Coastguard Worker 		} else {
122*2d543d20SAndroid Build Coastguard Worker 			if (!reason) {
123*2d543d20SAndroid Build Coastguard Worker 				foundlist[fcnt] = i;
124*2d543d20SAndroid Build Coastguard Worker 				fcnt++;
125*2d543d20SAndroid Build Coastguard Worker 			}
126*2d543d20SAndroid Build Coastguard Worker 			sepol_bool_set_value(boolean, active);
127*2d543d20SAndroid Build Coastguard Worker 			rc = sepol_bool_set(avc->handle,
128*2d543d20SAndroid Build Coastguard Worker 					    avc->policydb, key,
129*2d543d20SAndroid Build Coastguard Worker 					    boolean);
130*2d543d20SAndroid Build Coastguard Worker 			if (rc < 0) {
131*2d543d20SAndroid Build Coastguard Worker 				snprintf(errormsg, sizeof(errormsg),
132*2d543d20SAndroid Build Coastguard Worker 					 "Could not set boolean data %s.\n",
133*2d543d20SAndroid Build Coastguard Worker 					 name);
134*2d543d20SAndroid Build Coastguard Worker 
135*2d543d20SAndroid Build Coastguard Worker 				PyErr_SetString( PyExc_RuntimeError, errormsg);
136*2d543d20SAndroid Build Coastguard Worker 				break;
137*2d543d20SAndroid Build Coastguard Worker 			}
138*2d543d20SAndroid Build Coastguard Worker 		}
139*2d543d20SAndroid Build Coastguard Worker 		sepol_bool_free(boolean);
140*2d543d20SAndroid Build Coastguard Worker 		sepol_bool_key_free(key);
141*2d543d20SAndroid Build Coastguard Worker 		key = NULL;
142*2d543d20SAndroid Build Coastguard Worker 		boolean = NULL;
143*2d543d20SAndroid Build Coastguard Worker 	}
144*2d543d20SAndroid Build Coastguard Worker 	if (key)
145*2d543d20SAndroid Build Coastguard Worker 		sepol_bool_key_free(key);
146*2d543d20SAndroid Build Coastguard Worker 
147*2d543d20SAndroid Build Coastguard Worker 	if (boolean)
148*2d543d20SAndroid Build Coastguard Worker 		sepol_bool_free(boolean);
149*2d543d20SAndroid Build Coastguard Worker 
150*2d543d20SAndroid Build Coastguard Worker 	if (fcnt > 0) {
151*2d543d20SAndroid Build Coastguard Worker 		*bools = calloc(fcnt + 1, sizeof(struct boolean_t));
152*2d543d20SAndroid Build Coastguard Worker 		if (!*bools) {
153*2d543d20SAndroid Build Coastguard Worker 			PyErr_SetString( PyExc_MemoryError, "Out of memory\n");
154*2d543d20SAndroid Build Coastguard Worker 			free(foundlist);
155*2d543d20SAndroid Build Coastguard Worker 			return 0;
156*2d543d20SAndroid Build Coastguard Worker 		}
157*2d543d20SAndroid Build Coastguard Worker 
158*2d543d20SAndroid Build Coastguard Worker 		struct boolean_t *b = *bools;
159*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < fcnt; i++) {
160*2d543d20SAndroid Build Coastguard Worker 			int ctr = foundlist[i];
161*2d543d20SAndroid Build Coastguard Worker 			b[i].name = strdup(boollist[ctr]->name);
162*2d543d20SAndroid Build Coastguard Worker 			b[i].active = !boollist[ctr]->active;
163*2d543d20SAndroid Build Coastguard Worker 		}
164*2d543d20SAndroid Build Coastguard Worker 	}
165*2d543d20SAndroid Build Coastguard Worker 	free(foundlist);
166*2d543d20SAndroid Build Coastguard Worker 	return fcnt;
167*2d543d20SAndroid Build Coastguard Worker }
168*2d543d20SAndroid Build Coastguard Worker 
finish(PyObject * self,PyObject * args)169*2d543d20SAndroid Build Coastguard Worker static PyObject *finish(PyObject *self __attribute__((unused)), PyObject *args) {
170*2d543d20SAndroid Build Coastguard Worker 	PyObject *result = 0;
171*2d543d20SAndroid Build Coastguard Worker 
172*2d543d20SAndroid Build Coastguard Worker 	if (PyArg_ParseTuple(args,(char *)":finish")) {
173*2d543d20SAndroid Build Coastguard Worker 		int i = 0;
174*2d543d20SAndroid Build Coastguard Worker 		if (! avc)
175*2d543d20SAndroid Build Coastguard Worker 			Py_RETURN_NONE;
176*2d543d20SAndroid Build Coastguard Worker 
177*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < boolcnt; i++) {
178*2d543d20SAndroid Build Coastguard Worker 			free(boollist[i]->name);
179*2d543d20SAndroid Build Coastguard Worker 			free(boollist[i]);
180*2d543d20SAndroid Build Coastguard Worker 		}
181*2d543d20SAndroid Build Coastguard Worker 		free(boollist);
182*2d543d20SAndroid Build Coastguard Worker 		sepol_sidtab_shutdown(&sidtab);
183*2d543d20SAndroid Build Coastguard Worker 		sepol_sidtab_destroy(&sidtab);
184*2d543d20SAndroid Build Coastguard Worker 		sepol_policydb_free(avc->policydb);
185*2d543d20SAndroid Build Coastguard Worker 		sepol_handle_destroy(avc->handle);
186*2d543d20SAndroid Build Coastguard Worker 		free(avc);
187*2d543d20SAndroid Build Coastguard Worker 		avc = NULL;
188*2d543d20SAndroid Build Coastguard Worker 		boollist = NULL;
189*2d543d20SAndroid Build Coastguard Worker 		boolcnt = 0;
190*2d543d20SAndroid Build Coastguard Worker 
191*2d543d20SAndroid Build Coastguard Worker 		/* Boilerplate to return "None" */
192*2d543d20SAndroid Build Coastguard Worker 		Py_RETURN_NONE;
193*2d543d20SAndroid Build Coastguard Worker 	}
194*2d543d20SAndroid Build Coastguard Worker 	return result;
195*2d543d20SAndroid Build Coastguard Worker }
196*2d543d20SAndroid Build Coastguard Worker 
197*2d543d20SAndroid Build Coastguard Worker 
__policy_init(const char * init_path)198*2d543d20SAndroid Build Coastguard Worker static int __policy_init(const char *init_path)
199*2d543d20SAndroid Build Coastguard Worker {
200*2d543d20SAndroid Build Coastguard Worker 	FILE *fp = NULL;
201*2d543d20SAndroid Build Coastguard Worker 	const char *curpolicy;
202*2d543d20SAndroid Build Coastguard Worker 	char errormsg[PATH_MAX+1024+20];
203*2d543d20SAndroid Build Coastguard Worker 	struct sepol_policy_file *pf = NULL;
204*2d543d20SAndroid Build Coastguard Worker 	int rc;
205*2d543d20SAndroid Build Coastguard Worker 	unsigned int cnt;
206*2d543d20SAndroid Build Coastguard Worker 
207*2d543d20SAndroid Build Coastguard Worker 	if (init_path) {
208*2d543d20SAndroid Build Coastguard Worker 		curpolicy = init_path;
209*2d543d20SAndroid Build Coastguard Worker 	} else {
210*2d543d20SAndroid Build Coastguard Worker 		curpolicy = selinux_current_policy_path();
211*2d543d20SAndroid Build Coastguard Worker 		if (!curpolicy) {
212*2d543d20SAndroid Build Coastguard Worker 			/* SELinux disabled, must use -p option. */
213*2d543d20SAndroid Build Coastguard Worker 			snprintf(errormsg, sizeof(errormsg),
214*2d543d20SAndroid Build Coastguard Worker 				 "You must specify the -p option with the path to the policy file.\n");
215*2d543d20SAndroid Build Coastguard Worker 			PyErr_SetString( PyExc_ValueError, errormsg);
216*2d543d20SAndroid Build Coastguard Worker 			return 1;
217*2d543d20SAndroid Build Coastguard Worker 		}
218*2d543d20SAndroid Build Coastguard Worker 	}
219*2d543d20SAndroid Build Coastguard Worker 
220*2d543d20SAndroid Build Coastguard Worker 	fp = fopen(curpolicy, "re");
221*2d543d20SAndroid Build Coastguard Worker 	if (!fp) {
222*2d543d20SAndroid Build Coastguard Worker 		snprintf(errormsg, sizeof(errormsg),
223*2d543d20SAndroid Build Coastguard Worker 			 "unable to open %s:  %m\n",
224*2d543d20SAndroid Build Coastguard Worker 			 curpolicy);
225*2d543d20SAndroid Build Coastguard Worker 		PyErr_SetString( PyExc_ValueError, errormsg);
226*2d543d20SAndroid Build Coastguard Worker 		return 1;
227*2d543d20SAndroid Build Coastguard Worker 	}
228*2d543d20SAndroid Build Coastguard Worker 
229*2d543d20SAndroid Build Coastguard Worker 	avc = calloc(1, sizeof(struct avc_t));
230*2d543d20SAndroid Build Coastguard Worker 	if (!avc) {
231*2d543d20SAndroid Build Coastguard Worker 		PyErr_SetString( PyExc_MemoryError, "Out of memory\n");
232*2d543d20SAndroid Build Coastguard Worker 		fclose(fp);
233*2d543d20SAndroid Build Coastguard Worker 		return 1;
234*2d543d20SAndroid Build Coastguard Worker 	}
235*2d543d20SAndroid Build Coastguard Worker 
236*2d543d20SAndroid Build Coastguard Worker 	/* Set up a policydb directly so that we can mutate it later
237*2d543d20SAndroid Build Coastguard Worker 	   for testing what booleans might have allowed the access.
238*2d543d20SAndroid Build Coastguard Worker 	   Otherwise, we'd just use sepol_set_policydb_from_file() here. */
239*2d543d20SAndroid Build Coastguard Worker 	if (sepol_policy_file_create(&pf) ||
240*2d543d20SAndroid Build Coastguard Worker 	    sepol_policydb_create(&avc->policydb)) {
241*2d543d20SAndroid Build Coastguard Worker 		snprintf(errormsg, sizeof(errormsg),
242*2d543d20SAndroid Build Coastguard Worker 			 "policydb_init failed: %m\n");
243*2d543d20SAndroid Build Coastguard Worker 		PyErr_SetString( PyExc_RuntimeError, errormsg);
244*2d543d20SAndroid Build Coastguard Worker 		goto err;
245*2d543d20SAndroid Build Coastguard Worker 	}
246*2d543d20SAndroid Build Coastguard Worker 	sepol_policy_file_set_fp(pf, fp);
247*2d543d20SAndroid Build Coastguard Worker 	if (sepol_policydb_read(avc->policydb, pf)) {
248*2d543d20SAndroid Build Coastguard Worker 		snprintf(errormsg, sizeof(errormsg),
249*2d543d20SAndroid Build Coastguard Worker 			 "invalid binary policy %s\n", curpolicy);
250*2d543d20SAndroid Build Coastguard Worker 		PyErr_SetString( PyExc_ValueError, errormsg);
251*2d543d20SAndroid Build Coastguard Worker 		goto err;
252*2d543d20SAndroid Build Coastguard Worker 	}
253*2d543d20SAndroid Build Coastguard Worker 	fclose(fp);
254*2d543d20SAndroid Build Coastguard Worker 	fp = NULL;
255*2d543d20SAndroid Build Coastguard Worker 	sepol_set_policydb(&avc->policydb->p);
256*2d543d20SAndroid Build Coastguard Worker 	avc->handle = sepol_handle_create();
257*2d543d20SAndroid Build Coastguard Worker 	/* Turn off messages */
258*2d543d20SAndroid Build Coastguard Worker 	sepol_msg_set_callback(avc->handle, NULL, NULL);
259*2d543d20SAndroid Build Coastguard Worker 
260*2d543d20SAndroid Build Coastguard Worker 	rc = sepol_bool_count(avc->handle,
261*2d543d20SAndroid Build Coastguard Worker 			      avc->policydb, &cnt);
262*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0) {
263*2d543d20SAndroid Build Coastguard Worker 		PyErr_SetString( PyExc_RuntimeError, "unable to get bool count\n");
264*2d543d20SAndroid Build Coastguard Worker 		goto err;
265*2d543d20SAndroid Build Coastguard Worker 	}
266*2d543d20SAndroid Build Coastguard Worker 
267*2d543d20SAndroid Build Coastguard Worker 	boollist = calloc(cnt, sizeof(*boollist));
268*2d543d20SAndroid Build Coastguard Worker 	if (!boollist) {
269*2d543d20SAndroid Build Coastguard Worker 		PyErr_SetString( PyExc_MemoryError, "Out of memory\n");
270*2d543d20SAndroid Build Coastguard Worker 		goto err;
271*2d543d20SAndroid Build Coastguard Worker 	}
272*2d543d20SAndroid Build Coastguard Worker 
273*2d543d20SAndroid Build Coastguard Worker 	sepol_bool_iterate(avc->handle, avc->policydb,
274*2d543d20SAndroid Build Coastguard Worker 			   load_booleans, NULL);
275*2d543d20SAndroid Build Coastguard Worker 
276*2d543d20SAndroid Build Coastguard Worker 	/* Initialize the sidtab for subsequent use by sepol_context_to_sid
277*2d543d20SAndroid Build Coastguard Worker 	   and sepol_compute_av_reason. */
278*2d543d20SAndroid Build Coastguard Worker 	rc = sepol_sidtab_init(&sidtab);
279*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0) {
280*2d543d20SAndroid Build Coastguard Worker 		PyErr_SetString( PyExc_RuntimeError, "unable to init sidtab\n");
281*2d543d20SAndroid Build Coastguard Worker 		goto err;
282*2d543d20SAndroid Build Coastguard Worker 	}
283*2d543d20SAndroid Build Coastguard Worker 	sepol_set_sidtab(&sidtab);
284*2d543d20SAndroid Build Coastguard Worker 	return 0;
285*2d543d20SAndroid Build Coastguard Worker 
286*2d543d20SAndroid Build Coastguard Worker err:
287*2d543d20SAndroid Build Coastguard Worker 	if (boollist)
288*2d543d20SAndroid Build Coastguard Worker 		free(boollist);
289*2d543d20SAndroid Build Coastguard Worker 	if (avc){
290*2d543d20SAndroid Build Coastguard Worker 		if (avc->handle)
291*2d543d20SAndroid Build Coastguard Worker 			sepol_handle_destroy(avc->handle);
292*2d543d20SAndroid Build Coastguard Worker 		if (avc->policydb)
293*2d543d20SAndroid Build Coastguard Worker 			sepol_policydb_free(avc->policydb);
294*2d543d20SAndroid Build Coastguard Worker 		free(avc);
295*2d543d20SAndroid Build Coastguard Worker 	}
296*2d543d20SAndroid Build Coastguard Worker 	if (pf)
297*2d543d20SAndroid Build Coastguard Worker 		sepol_policy_file_free(pf);
298*2d543d20SAndroid Build Coastguard Worker 	if (fp)
299*2d543d20SAndroid Build Coastguard Worker 		fclose(fp);
300*2d543d20SAndroid Build Coastguard Worker 	return 1;
301*2d543d20SAndroid Build Coastguard Worker }
302*2d543d20SAndroid Build Coastguard Worker 
init(PyObject * self,PyObject * args)303*2d543d20SAndroid Build Coastguard Worker static PyObject *init(PyObject *self __attribute__((unused)), PyObject *args) {
304*2d543d20SAndroid Build Coastguard Worker   int result;
305*2d543d20SAndroid Build Coastguard Worker   char *init_path = NULL;
306*2d543d20SAndroid Build Coastguard Worker   if (avc) {
307*2d543d20SAndroid Build Coastguard Worker 	  PyErr_SetString( PyExc_RuntimeError, "init called multiple times");
308*2d543d20SAndroid Build Coastguard Worker 	  return NULL;
309*2d543d20SAndroid Build Coastguard Worker   }
310*2d543d20SAndroid Build Coastguard Worker   if (!PyArg_ParseTuple(args,(char *)"|s:policy_init",&init_path))
311*2d543d20SAndroid Build Coastguard Worker     return NULL;
312*2d543d20SAndroid Build Coastguard Worker   result = __policy_init(init_path);
313*2d543d20SAndroid Build Coastguard Worker   return Py_BuildValue("i", result);
314*2d543d20SAndroid Build Coastguard Worker }
315*2d543d20SAndroid Build Coastguard Worker 
316*2d543d20SAndroid Build Coastguard Worker #define RETURN(X) \
317*2d543d20SAndroid Build Coastguard Worker 	{ \
318*2d543d20SAndroid Build Coastguard Worker 		return Py_BuildValue("iO", (X), Py_None);	\
319*2d543d20SAndroid Build Coastguard Worker 	}
320*2d543d20SAndroid Build Coastguard Worker 
analyze(PyObject * self,PyObject * args)321*2d543d20SAndroid Build Coastguard Worker static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args) {
322*2d543d20SAndroid Build Coastguard Worker 	char *reason_buf = NULL;
323*2d543d20SAndroid Build Coastguard Worker 	char * scon;
324*2d543d20SAndroid Build Coastguard Worker 	char * tcon;
325*2d543d20SAndroid Build Coastguard Worker 	char *tclassstr;
326*2d543d20SAndroid Build Coastguard Worker 	PyObject *listObj;
327*2d543d20SAndroid Build Coastguard Worker 	PyObject *strObj;
328*2d543d20SAndroid Build Coastguard Worker 	int numlines;
329*2d543d20SAndroid Build Coastguard Worker 	struct boolean_t *bools;
330*2d543d20SAndroid Build Coastguard Worker 	unsigned int reason;
331*2d543d20SAndroid Build Coastguard Worker 	sepol_security_id_t ssid, tsid;
332*2d543d20SAndroid Build Coastguard Worker 	sepol_security_class_t tclass;
333*2d543d20SAndroid Build Coastguard Worker 	sepol_access_vector_t perm, av;
334*2d543d20SAndroid Build Coastguard Worker 	struct sepol_av_decision avd;
335*2d543d20SAndroid Build Coastguard Worker 	int rc;
336*2d543d20SAndroid Build Coastguard Worker 	int i = 0;
337*2d543d20SAndroid Build Coastguard Worker 
338*2d543d20SAndroid Build Coastguard Worker 	if (!PyArg_ParseTuple(args,(char *)"sssO!:audit2why",&scon,&tcon,&tclassstr,&PyList_Type, &listObj))
339*2d543d20SAndroid Build Coastguard Worker 		return NULL;
340*2d543d20SAndroid Build Coastguard Worker 
341*2d543d20SAndroid Build Coastguard Worker 	/* get the number of lines passed to us */
342*2d543d20SAndroid Build Coastguard Worker 	numlines = PyList_Size(listObj);
343*2d543d20SAndroid Build Coastguard Worker 
344*2d543d20SAndroid Build Coastguard Worker 	/* should raise an error here. */
345*2d543d20SAndroid Build Coastguard Worker 	if (numlines < 0)	return NULL; /* Not a list */
346*2d543d20SAndroid Build Coastguard Worker 
347*2d543d20SAndroid Build Coastguard Worker 	if (!avc)
348*2d543d20SAndroid Build Coastguard Worker 		RETURN(NOPOLICY)
349*2d543d20SAndroid Build Coastguard Worker 
350*2d543d20SAndroid Build Coastguard Worker 	rc = sepol_context_to_sid(scon, strlen(scon) + 1, &ssid);
351*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0)
352*2d543d20SAndroid Build Coastguard Worker 		RETURN(BADSCON)
353*2d543d20SAndroid Build Coastguard Worker 
354*2d543d20SAndroid Build Coastguard Worker 	rc = sepol_context_to_sid(tcon, strlen(tcon) + 1, &tsid);
355*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0)
356*2d543d20SAndroid Build Coastguard Worker 		RETURN(BADTCON)
357*2d543d20SAndroid Build Coastguard Worker 
358*2d543d20SAndroid Build Coastguard Worker 	rc = sepol_string_to_security_class(tclassstr, &tclass);
359*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0)
360*2d543d20SAndroid Build Coastguard Worker 		RETURN(BADTCLASS)
361*2d543d20SAndroid Build Coastguard Worker 
362*2d543d20SAndroid Build Coastguard Worker 	/* Convert the permission list to an AV. */
363*2d543d20SAndroid Build Coastguard Worker 	av = 0;
364*2d543d20SAndroid Build Coastguard Worker 
365*2d543d20SAndroid Build Coastguard Worker 	/* iterate over items of the list, grabbing strings, and parsing
366*2d543d20SAndroid Build Coastguard Worker 	   for numbers */
367*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < numlines; i++){
368*2d543d20SAndroid Build Coastguard Worker 		const char *permstr;
369*2d543d20SAndroid Build Coastguard Worker 
370*2d543d20SAndroid Build Coastguard Worker 		/* grab the string object from the next element of the list */
371*2d543d20SAndroid Build Coastguard Worker 		strObj = PyList_GetItem(listObj, i); /* Can't fail */
372*2d543d20SAndroid Build Coastguard Worker 
373*2d543d20SAndroid Build Coastguard Worker 		/* make it a string */
374*2d543d20SAndroid Build Coastguard Worker #if PY_MAJOR_VERSION >= 3
375*2d543d20SAndroid Build Coastguard Worker 		permstr = _PyUnicode_AsString( strObj );
376*2d543d20SAndroid Build Coastguard Worker #else
377*2d543d20SAndroid Build Coastguard Worker 		permstr = PyString_AsString( strObj );
378*2d543d20SAndroid Build Coastguard Worker #endif
379*2d543d20SAndroid Build Coastguard Worker 
380*2d543d20SAndroid Build Coastguard Worker 		rc = sepol_string_to_av_perm(tclass, permstr, &perm);
381*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0)
382*2d543d20SAndroid Build Coastguard Worker 			RETURN(BADPERM)
383*2d543d20SAndroid Build Coastguard Worker 
384*2d543d20SAndroid Build Coastguard Worker 		av |= perm;
385*2d543d20SAndroid Build Coastguard Worker 	}
386*2d543d20SAndroid Build Coastguard Worker 
387*2d543d20SAndroid Build Coastguard Worker 	/* Reproduce the computation. */
388*2d543d20SAndroid Build Coastguard Worker 	rc = sepol_compute_av_reason_buffer(ssid, tsid, tclass, av, &avd, &reason, &reason_buf, 0);
389*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0)
390*2d543d20SAndroid Build Coastguard Worker 		RETURN(BADCOMPUTE)
391*2d543d20SAndroid Build Coastguard Worker 
392*2d543d20SAndroid Build Coastguard Worker 	if (!reason)
393*2d543d20SAndroid Build Coastguard Worker 		RETURN(ALLOW)
394*2d543d20SAndroid Build Coastguard Worker 
395*2d543d20SAndroid Build Coastguard Worker 	if (reason & SEPOL_COMPUTEAV_TE) {
396*2d543d20SAndroid Build Coastguard Worker 		avc->ssid = ssid;
397*2d543d20SAndroid Build Coastguard Worker 		avc->tsid = tsid;
398*2d543d20SAndroid Build Coastguard Worker 		avc->tclass = tclass;
399*2d543d20SAndroid Build Coastguard Worker 		avc->av = av;
400*2d543d20SAndroid Build Coastguard Worker 		if (check_booleans(&bools) == 0) {
401*2d543d20SAndroid Build Coastguard Worker 			if (av & ~avd.auditdeny) {
402*2d543d20SAndroid Build Coastguard Worker 				RETURN(DONTAUDIT)
403*2d543d20SAndroid Build Coastguard Worker 			} else {
404*2d543d20SAndroid Build Coastguard Worker 				RETURN(TERULE)
405*2d543d20SAndroid Build Coastguard Worker 			}
406*2d543d20SAndroid Build Coastguard Worker 		} else {
407*2d543d20SAndroid Build Coastguard Worker 			PyObject *outboollist;
408*2d543d20SAndroid Build Coastguard Worker 			struct boolean_t *b = bools;
409*2d543d20SAndroid Build Coastguard Worker 			int len = 0;
410*2d543d20SAndroid Build Coastguard Worker 			while (b->name) {
411*2d543d20SAndroid Build Coastguard Worker 				len++; b++;
412*2d543d20SAndroid Build Coastguard Worker 			}
413*2d543d20SAndroid Build Coastguard Worker 			b = bools;
414*2d543d20SAndroid Build Coastguard Worker 			outboollist = PyList_New(len);
415*2d543d20SAndroid Build Coastguard Worker 			len = 0;
416*2d543d20SAndroid Build Coastguard Worker 			while(b->name) {
417*2d543d20SAndroid Build Coastguard Worker 				PyObject *bool_ = Py_BuildValue("(si)", b->name, b->active);
418*2d543d20SAndroid Build Coastguard Worker 				PyList_SetItem(outboollist, len++, bool_);
419*2d543d20SAndroid Build Coastguard Worker 				b++;
420*2d543d20SAndroid Build Coastguard Worker 			}
421*2d543d20SAndroid Build Coastguard Worker 			free(bools);
422*2d543d20SAndroid Build Coastguard Worker 			/* 'N' steals the reference to outboollist */
423*2d543d20SAndroid Build Coastguard Worker 			return Py_BuildValue("iN", BOOLEAN, outboollist);
424*2d543d20SAndroid Build Coastguard Worker 		}
425*2d543d20SAndroid Build Coastguard Worker 	}
426*2d543d20SAndroid Build Coastguard Worker 
427*2d543d20SAndroid Build Coastguard Worker 	if (reason & SEPOL_COMPUTEAV_CONS) {
428*2d543d20SAndroid Build Coastguard Worker 		if (reason_buf) {
429*2d543d20SAndroid Build Coastguard Worker 			PyObject *result = NULL;
430*2d543d20SAndroid Build Coastguard Worker 			result = Py_BuildValue("is", CONSTRAINT, reason_buf);
431*2d543d20SAndroid Build Coastguard Worker 			free(reason_buf);
432*2d543d20SAndroid Build Coastguard Worker 			return result;
433*2d543d20SAndroid Build Coastguard Worker 		}
434*2d543d20SAndroid Build Coastguard Worker 		RETURN(CONSTRAINT)
435*2d543d20SAndroid Build Coastguard Worker 	}
436*2d543d20SAndroid Build Coastguard Worker 
437*2d543d20SAndroid Build Coastguard Worker 	if (reason & SEPOL_COMPUTEAV_RBAC)
438*2d543d20SAndroid Build Coastguard Worker 		RETURN(RBAC)
439*2d543d20SAndroid Build Coastguard Worker 
440*2d543d20SAndroid Build Coastguard Worker 	if (reason & SEPOL_COMPUTEAV_BOUNDS)
441*2d543d20SAndroid Build Coastguard Worker 		RETURN(BOUNDS)
442*2d543d20SAndroid Build Coastguard Worker 
443*2d543d20SAndroid Build Coastguard Worker         RETURN(BADCOMPUTE)
444*2d543d20SAndroid Build Coastguard Worker }
445*2d543d20SAndroid Build Coastguard Worker 
446*2d543d20SAndroid Build Coastguard Worker static PyMethodDef audit2whyMethods[] = {
447*2d543d20SAndroid Build Coastguard Worker     {"init",  init, METH_VARARGS,
448*2d543d20SAndroid Build Coastguard Worker      "Initialize policy database."},
449*2d543d20SAndroid Build Coastguard Worker     {"analyze",  analyze, METH_VARARGS,
450*2d543d20SAndroid Build Coastguard Worker      "Analyze AVC."},
451*2d543d20SAndroid Build Coastguard Worker     {"finish",  finish, METH_VARARGS,
452*2d543d20SAndroid Build Coastguard Worker      "Finish using policy, free memory."},
453*2d543d20SAndroid Build Coastguard Worker     {NULL, NULL, 0, NULL}        /* Sentinel */
454*2d543d20SAndroid Build Coastguard Worker };
455*2d543d20SAndroid Build Coastguard Worker 
456*2d543d20SAndroid Build Coastguard Worker #if PY_MAJOR_VERSION >= 3
457*2d543d20SAndroid Build Coastguard Worker /* Module-initialization logic specific to Python 3 */
458*2d543d20SAndroid Build Coastguard Worker static struct PyModuleDef moduledef = {
459*2d543d20SAndroid Build Coastguard Worker 	PyModuleDef_HEAD_INIT,
460*2d543d20SAndroid Build Coastguard Worker 	"audit2why",
461*2d543d20SAndroid Build Coastguard Worker 	NULL,
462*2d543d20SAndroid Build Coastguard Worker 	0,
463*2d543d20SAndroid Build Coastguard Worker 	audit2whyMethods,
464*2d543d20SAndroid Build Coastguard Worker 	NULL,
465*2d543d20SAndroid Build Coastguard Worker 	NULL,
466*2d543d20SAndroid Build Coastguard Worker 	NULL,
467*2d543d20SAndroid Build Coastguard Worker 	NULL
468*2d543d20SAndroid Build Coastguard Worker };
469*2d543d20SAndroid Build Coastguard Worker 
470*2d543d20SAndroid Build Coastguard Worker PyMODINIT_FUNC PyInit_audit2why(void); /* silence -Wmissing-prototypes */
PyInit_audit2why(void)471*2d543d20SAndroid Build Coastguard Worker PyMODINIT_FUNC PyInit_audit2why(void)
472*2d543d20SAndroid Build Coastguard Worker #else
473*2d543d20SAndroid Build Coastguard Worker PyMODINIT_FUNC initaudit2why(void); /* silence -Wmissing-prototypes */
474*2d543d20SAndroid Build Coastguard Worker PyMODINIT_FUNC initaudit2why(void)
475*2d543d20SAndroid Build Coastguard Worker #endif
476*2d543d20SAndroid Build Coastguard Worker {
477*2d543d20SAndroid Build Coastguard Worker 	PyObject *m;
478*2d543d20SAndroid Build Coastguard Worker #if PY_MAJOR_VERSION >= 3
479*2d543d20SAndroid Build Coastguard Worker 	m = PyModule_Create(&moduledef);
480*2d543d20SAndroid Build Coastguard Worker 	if (m == NULL) {
481*2d543d20SAndroid Build Coastguard Worker 		return NULL;
482*2d543d20SAndroid Build Coastguard Worker 	}
483*2d543d20SAndroid Build Coastguard Worker #else
484*2d543d20SAndroid Build Coastguard Worker 	m  = Py_InitModule("audit2why", audit2whyMethods);
485*2d543d20SAndroid Build Coastguard Worker #endif
486*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"UNKNOWN", UNKNOWN);
487*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"BADSCON", BADSCON);
488*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"BADTCON", BADTCON);
489*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"BADTCLASS", BADTCLASS);
490*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"BADPERM", BADPERM);
491*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"BADCOMPUTE", BADCOMPUTE);
492*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"NOPOLICY", NOPOLICY);
493*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"ALLOW", ALLOW);
494*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"DONTAUDIT", DONTAUDIT);
495*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"TERULE", TERULE);
496*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"BOOLEAN", BOOLEAN);
497*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"CONSTRAINT", CONSTRAINT);
498*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"RBAC", RBAC);
499*2d543d20SAndroid Build Coastguard Worker 	PyModule_AddIntConstant(m,"BOUNDS", BOUNDS);
500*2d543d20SAndroid Build Coastguard Worker 
501*2d543d20SAndroid Build Coastguard Worker #if PY_MAJOR_VERSION >= 3
502*2d543d20SAndroid Build Coastguard Worker 	return m;
503*2d543d20SAndroid Build Coastguard Worker #endif
504*2d543d20SAndroid Build Coastguard Worker }
505