16cd6a6acSopenharmony_ci/* Workaround for http://bugs.python.org/issue4835 */
26cd6a6acSopenharmony_ci#ifndef SIZEOF_SOCKET_T
36cd6a6acSopenharmony_ci#define SIZEOF_SOCKET_T SIZEOF_INT
46cd6a6acSopenharmony_ci#endif
56cd6a6acSopenharmony_ci
66cd6a6acSopenharmony_ci#include <Python.h>
76cd6a6acSopenharmony_ci#include <unistd.h>
86cd6a6acSopenharmony_ci#include <stdlib.h>
96cd6a6acSopenharmony_ci#include <ctype.h>
106cd6a6acSopenharmony_ci#include <errno.h>
116cd6a6acSopenharmony_ci#include <getopt.h>
126cd6a6acSopenharmony_ci#include <limits.h>
136cd6a6acSopenharmony_ci#include <sepol/sepol.h>
146cd6a6acSopenharmony_ci#include <sepol/policydb.h>
156cd6a6acSopenharmony_ci#include <sepol/policydb/services.h>
166cd6a6acSopenharmony_ci#include <selinux/selinux.h>
176cd6a6acSopenharmony_ci
186cd6a6acSopenharmony_ci#define UNKNOWN -1
196cd6a6acSopenharmony_ci#define BADSCON -2
206cd6a6acSopenharmony_ci#define BADTCON -3
216cd6a6acSopenharmony_ci#define BADTCLASS -4
226cd6a6acSopenharmony_ci#define BADPERM -5
236cd6a6acSopenharmony_ci#define BADCOMPUTE -6
246cd6a6acSopenharmony_ci#define NOPOLICY -7
256cd6a6acSopenharmony_ci#define ALLOW 0
266cd6a6acSopenharmony_ci#define DONTAUDIT 1
276cd6a6acSopenharmony_ci#define TERULE 2
286cd6a6acSopenharmony_ci#define BOOLEAN 3
296cd6a6acSopenharmony_ci#define CONSTRAINT 4
306cd6a6acSopenharmony_ci#define RBAC 5
316cd6a6acSopenharmony_ci#define BOUNDS 6
326cd6a6acSopenharmony_ci
336cd6a6acSopenharmony_cistruct boolean_t {
346cd6a6acSopenharmony_ci	char *name;
356cd6a6acSopenharmony_ci	int active;
366cd6a6acSopenharmony_ci};
376cd6a6acSopenharmony_ci
386cd6a6acSopenharmony_cistatic struct boolean_t **boollist = NULL;
396cd6a6acSopenharmony_cistatic int boolcnt = 0;
406cd6a6acSopenharmony_ci
416cd6a6acSopenharmony_cistruct avc_t {
426cd6a6acSopenharmony_ci	sepol_handle_t *handle;
436cd6a6acSopenharmony_ci	sepol_policydb_t *policydb;
446cd6a6acSopenharmony_ci	sepol_security_id_t ssid;
456cd6a6acSopenharmony_ci	sepol_security_id_t tsid;
466cd6a6acSopenharmony_ci	sepol_security_class_t tclass;
476cd6a6acSopenharmony_ci	sepol_access_vector_t av;
486cd6a6acSopenharmony_ci};
496cd6a6acSopenharmony_ci
506cd6a6acSopenharmony_cistatic struct avc_t *avc = NULL;
516cd6a6acSopenharmony_ci
526cd6a6acSopenharmony_cistatic sidtab_t sidtab;
536cd6a6acSopenharmony_ci
546cd6a6acSopenharmony_cistatic int load_booleans(const sepol_bool_t * boolean,
556cd6a6acSopenharmony_ci			 void *arg __attribute__ ((__unused__)))
566cd6a6acSopenharmony_ci{
576cd6a6acSopenharmony_ci	boollist[boolcnt] = malloc(sizeof(struct boolean_t));
586cd6a6acSopenharmony_ci	boollist[boolcnt]->name = strdup(sepol_bool_get_name(boolean));
596cd6a6acSopenharmony_ci	boollist[boolcnt]->active = sepol_bool_get_value(boolean);
606cd6a6acSopenharmony_ci	boolcnt++;
616cd6a6acSopenharmony_ci	return 0;
626cd6a6acSopenharmony_ci}
636cd6a6acSopenharmony_ci
646cd6a6acSopenharmony_cistatic int check_booleans(struct boolean_t **bools)
656cd6a6acSopenharmony_ci{
666cd6a6acSopenharmony_ci	char errormsg[PATH_MAX];
676cd6a6acSopenharmony_ci	struct sepol_av_decision avd;
686cd6a6acSopenharmony_ci	unsigned int reason;
696cd6a6acSopenharmony_ci	int rc;
706cd6a6acSopenharmony_ci	int i;
716cd6a6acSopenharmony_ci	sepol_bool_key_t *key = NULL;
726cd6a6acSopenharmony_ci	sepol_bool_t *boolean = NULL;
736cd6a6acSopenharmony_ci	int fcnt = 0;
746cd6a6acSopenharmony_ci	int *foundlist = calloc(boolcnt, sizeof(int));
756cd6a6acSopenharmony_ci	if (!foundlist) {
766cd6a6acSopenharmony_ci		PyErr_SetString( PyExc_MemoryError, "Out of memory\n");
776cd6a6acSopenharmony_ci		return fcnt;
786cd6a6acSopenharmony_ci	}
796cd6a6acSopenharmony_ci	for (i = 0; i < boolcnt; i++) {
806cd6a6acSopenharmony_ci		char *name = boollist[i]->name;
816cd6a6acSopenharmony_ci		int active = boollist[i]->active;
826cd6a6acSopenharmony_ci		rc = sepol_bool_key_create(avc->handle, name, &key);
836cd6a6acSopenharmony_ci		if (rc < 0) {
846cd6a6acSopenharmony_ci			PyErr_SetString( PyExc_RuntimeError,
856cd6a6acSopenharmony_ci					 "Could not create boolean key.\n");
866cd6a6acSopenharmony_ci			break;
876cd6a6acSopenharmony_ci		}
886cd6a6acSopenharmony_ci		rc = sepol_bool_query(avc->handle,
896cd6a6acSopenharmony_ci				      avc->policydb,
906cd6a6acSopenharmony_ci				      key, &boolean);
916cd6a6acSopenharmony_ci
926cd6a6acSopenharmony_ci		if (rc < 0) {
936cd6a6acSopenharmony_ci			snprintf(errormsg, sizeof(errormsg),
946cd6a6acSopenharmony_ci				 "Could not find boolean %s.\n", name);
956cd6a6acSopenharmony_ci			PyErr_SetString( PyExc_RuntimeError, errormsg);
966cd6a6acSopenharmony_ci			break;
976cd6a6acSopenharmony_ci		}
986cd6a6acSopenharmony_ci
996cd6a6acSopenharmony_ci		sepol_bool_set_value(boolean, !active);
1006cd6a6acSopenharmony_ci
1016cd6a6acSopenharmony_ci		rc = sepol_bool_set(avc->handle,
1026cd6a6acSopenharmony_ci				    avc->policydb,
1036cd6a6acSopenharmony_ci				    key, boolean);
1046cd6a6acSopenharmony_ci		if (rc < 0) {
1056cd6a6acSopenharmony_ci			snprintf(errormsg, sizeof(errormsg),
1066cd6a6acSopenharmony_ci				 "Could not set boolean data %s.\n", name);
1076cd6a6acSopenharmony_ci			PyErr_SetString( PyExc_RuntimeError, errormsg);
1086cd6a6acSopenharmony_ci			break;
1096cd6a6acSopenharmony_ci		}
1106cd6a6acSopenharmony_ci
1116cd6a6acSopenharmony_ci		/* Reproduce the computation. */
1126cd6a6acSopenharmony_ci		rc = sepol_compute_av_reason(avc->ssid, avc->tsid, avc->tclass,
1136cd6a6acSopenharmony_ci					     avc->av, &avd, &reason);
1146cd6a6acSopenharmony_ci		if (rc < 0) {
1156cd6a6acSopenharmony_ci			snprintf(errormsg, sizeof(errormsg),
1166cd6a6acSopenharmony_ci				 "Error during access vector computation, skipping...");
1176cd6a6acSopenharmony_ci			PyErr_SetString( PyExc_RuntimeError, errormsg);
1186cd6a6acSopenharmony_ci
1196cd6a6acSopenharmony_ci			sepol_bool_free(boolean);
1206cd6a6acSopenharmony_ci			break;
1216cd6a6acSopenharmony_ci		} else {
1226cd6a6acSopenharmony_ci			if (!reason) {
1236cd6a6acSopenharmony_ci				foundlist[fcnt] = i;
1246cd6a6acSopenharmony_ci				fcnt++;
1256cd6a6acSopenharmony_ci			}
1266cd6a6acSopenharmony_ci			sepol_bool_set_value(boolean, active);
1276cd6a6acSopenharmony_ci			rc = sepol_bool_set(avc->handle,
1286cd6a6acSopenharmony_ci					    avc->policydb, key,
1296cd6a6acSopenharmony_ci					    boolean);
1306cd6a6acSopenharmony_ci			if (rc < 0) {
1316cd6a6acSopenharmony_ci				snprintf(errormsg, sizeof(errormsg),
1326cd6a6acSopenharmony_ci					 "Could not set boolean data %s.\n",
1336cd6a6acSopenharmony_ci					 name);
1346cd6a6acSopenharmony_ci
1356cd6a6acSopenharmony_ci				PyErr_SetString( PyExc_RuntimeError, errormsg);
1366cd6a6acSopenharmony_ci				break;
1376cd6a6acSopenharmony_ci			}
1386cd6a6acSopenharmony_ci		}
1396cd6a6acSopenharmony_ci		sepol_bool_free(boolean);
1406cd6a6acSopenharmony_ci		sepol_bool_key_free(key);
1416cd6a6acSopenharmony_ci		key = NULL;
1426cd6a6acSopenharmony_ci		boolean = NULL;
1436cd6a6acSopenharmony_ci	}
1446cd6a6acSopenharmony_ci	if (key)
1456cd6a6acSopenharmony_ci		sepol_bool_key_free(key);
1466cd6a6acSopenharmony_ci
1476cd6a6acSopenharmony_ci	if (boolean)
1486cd6a6acSopenharmony_ci		sepol_bool_free(boolean);
1496cd6a6acSopenharmony_ci
1506cd6a6acSopenharmony_ci	if (fcnt > 0) {
1516cd6a6acSopenharmony_ci		*bools = calloc(sizeof(struct boolean_t), fcnt + 1);
1526cd6a6acSopenharmony_ci		struct boolean_t *b = *bools;
1536cd6a6acSopenharmony_ci		for (i = 0; i < fcnt; i++) {
1546cd6a6acSopenharmony_ci			int ctr = foundlist[i];
1556cd6a6acSopenharmony_ci			b[i].name = strdup(boollist[ctr]->name);
1566cd6a6acSopenharmony_ci			b[i].active = !boollist[ctr]->active;
1576cd6a6acSopenharmony_ci		}
1586cd6a6acSopenharmony_ci	}
1596cd6a6acSopenharmony_ci	free(foundlist);
1606cd6a6acSopenharmony_ci	return fcnt;
1616cd6a6acSopenharmony_ci}
1626cd6a6acSopenharmony_ci
1636cd6a6acSopenharmony_cistatic PyObject *finish(PyObject *self __attribute__((unused)), PyObject *args) {
1646cd6a6acSopenharmony_ci	PyObject *result = 0;
1656cd6a6acSopenharmony_ci
1666cd6a6acSopenharmony_ci	if (PyArg_ParseTuple(args,(char *)":finish")) {
1676cd6a6acSopenharmony_ci		int i = 0;
1686cd6a6acSopenharmony_ci		if (! avc)
1696cd6a6acSopenharmony_ci			Py_RETURN_NONE;
1706cd6a6acSopenharmony_ci
1716cd6a6acSopenharmony_ci		for (i = 0; i < boolcnt; i++) {
1726cd6a6acSopenharmony_ci			free(boollist[i]->name);
1736cd6a6acSopenharmony_ci			free(boollist[i]);
1746cd6a6acSopenharmony_ci		}
1756cd6a6acSopenharmony_ci		free(boollist);
1766cd6a6acSopenharmony_ci		sepol_sidtab_shutdown(&sidtab);
1776cd6a6acSopenharmony_ci		sepol_sidtab_destroy(&sidtab);
1786cd6a6acSopenharmony_ci		sepol_policydb_free(avc->policydb);
1796cd6a6acSopenharmony_ci		sepol_handle_destroy(avc->handle);
1806cd6a6acSopenharmony_ci		free(avc);
1816cd6a6acSopenharmony_ci		avc = NULL;
1826cd6a6acSopenharmony_ci		boollist = NULL;
1836cd6a6acSopenharmony_ci		boolcnt = 0;
1846cd6a6acSopenharmony_ci
1856cd6a6acSopenharmony_ci		/* Boilerplate to return "None" */
1866cd6a6acSopenharmony_ci		Py_RETURN_NONE;
1876cd6a6acSopenharmony_ci	}
1886cd6a6acSopenharmony_ci	return result;
1896cd6a6acSopenharmony_ci}
1906cd6a6acSopenharmony_ci
1916cd6a6acSopenharmony_ci
1926cd6a6acSopenharmony_cistatic int __policy_init(const char *init_path)
1936cd6a6acSopenharmony_ci{
1946cd6a6acSopenharmony_ci	FILE *fp = NULL;
1956cd6a6acSopenharmony_ci	const char *curpolicy;
1966cd6a6acSopenharmony_ci	char errormsg[PATH_MAX+1024+20];
1976cd6a6acSopenharmony_ci	struct sepol_policy_file *pf = NULL;
1986cd6a6acSopenharmony_ci	int rc;
1996cd6a6acSopenharmony_ci	unsigned int cnt;
2006cd6a6acSopenharmony_ci
2016cd6a6acSopenharmony_ci	if (init_path) {
2026cd6a6acSopenharmony_ci		curpolicy = init_path;
2036cd6a6acSopenharmony_ci	} else {
2046cd6a6acSopenharmony_ci		curpolicy = selinux_current_policy_path();
2056cd6a6acSopenharmony_ci		if (!curpolicy) {
2066cd6a6acSopenharmony_ci			/* SELinux disabled, must use -p option. */
2076cd6a6acSopenharmony_ci			snprintf(errormsg, sizeof(errormsg),
2086cd6a6acSopenharmony_ci				 "You must specify the -p option with the path to the policy file.\n");
2096cd6a6acSopenharmony_ci			PyErr_SetString( PyExc_ValueError, errormsg);
2106cd6a6acSopenharmony_ci			return 1;
2116cd6a6acSopenharmony_ci		}
2126cd6a6acSopenharmony_ci	}
2136cd6a6acSopenharmony_ci
2146cd6a6acSopenharmony_ci	fp = fopen(curpolicy, "re");
2156cd6a6acSopenharmony_ci	if (!fp) {
2166cd6a6acSopenharmony_ci		snprintf(errormsg, sizeof(errormsg),
2176cd6a6acSopenharmony_ci			 "unable to open %s:  %m\n",
2186cd6a6acSopenharmony_ci			 curpolicy);
2196cd6a6acSopenharmony_ci		PyErr_SetString( PyExc_ValueError, errormsg);
2206cd6a6acSopenharmony_ci		return 1;
2216cd6a6acSopenharmony_ci	}
2226cd6a6acSopenharmony_ci
2236cd6a6acSopenharmony_ci	avc = calloc(sizeof(struct avc_t), 1);
2246cd6a6acSopenharmony_ci	if (!avc) {
2256cd6a6acSopenharmony_ci		PyErr_SetString( PyExc_MemoryError, "Out of memory\n");
2266cd6a6acSopenharmony_ci		fclose(fp);
2276cd6a6acSopenharmony_ci		return 1;
2286cd6a6acSopenharmony_ci	}
2296cd6a6acSopenharmony_ci
2306cd6a6acSopenharmony_ci	/* Set up a policydb directly so that we can mutate it later
2316cd6a6acSopenharmony_ci	   for testing what booleans might have allowed the access.
2326cd6a6acSopenharmony_ci	   Otherwise, we'd just use sepol_set_policydb_from_file() here. */
2336cd6a6acSopenharmony_ci	if (sepol_policy_file_create(&pf) ||
2346cd6a6acSopenharmony_ci	    sepol_policydb_create(&avc->policydb)) {
2356cd6a6acSopenharmony_ci		snprintf(errormsg, sizeof(errormsg),
2366cd6a6acSopenharmony_ci			 "policydb_init failed: %m\n");
2376cd6a6acSopenharmony_ci		PyErr_SetString( PyExc_RuntimeError, errormsg);
2386cd6a6acSopenharmony_ci		goto err;
2396cd6a6acSopenharmony_ci	}
2406cd6a6acSopenharmony_ci	sepol_policy_file_set_fp(pf, fp);
2416cd6a6acSopenharmony_ci	if (sepol_policydb_read(avc->policydb, pf)) {
2426cd6a6acSopenharmony_ci		snprintf(errormsg, sizeof(errormsg),
2436cd6a6acSopenharmony_ci			 "invalid binary policy %s\n", curpolicy);
2446cd6a6acSopenharmony_ci		PyErr_SetString( PyExc_ValueError, errormsg);
2456cd6a6acSopenharmony_ci		goto err;
2466cd6a6acSopenharmony_ci	}
2476cd6a6acSopenharmony_ci	fclose(fp);
2486cd6a6acSopenharmony_ci	fp = NULL;
2496cd6a6acSopenharmony_ci	sepol_set_policydb(&avc->policydb->p);
2506cd6a6acSopenharmony_ci	avc->handle = sepol_handle_create();
2516cd6a6acSopenharmony_ci	/* Turn off messages */
2526cd6a6acSopenharmony_ci	sepol_msg_set_callback(avc->handle, NULL, NULL);
2536cd6a6acSopenharmony_ci
2546cd6a6acSopenharmony_ci	rc = sepol_bool_count(avc->handle,
2556cd6a6acSopenharmony_ci			      avc->policydb, &cnt);
2566cd6a6acSopenharmony_ci	if (rc < 0) {
2576cd6a6acSopenharmony_ci		PyErr_SetString( PyExc_RuntimeError, "unable to get bool count\n");
2586cd6a6acSopenharmony_ci		goto err;
2596cd6a6acSopenharmony_ci	}
2606cd6a6acSopenharmony_ci
2616cd6a6acSopenharmony_ci	boollist = calloc(cnt, sizeof(*boollist));
2626cd6a6acSopenharmony_ci	if (!boollist) {
2636cd6a6acSopenharmony_ci		PyErr_SetString( PyExc_MemoryError, "Out of memory\n");
2646cd6a6acSopenharmony_ci		goto err;
2656cd6a6acSopenharmony_ci	}
2666cd6a6acSopenharmony_ci
2676cd6a6acSopenharmony_ci	sepol_bool_iterate(avc->handle, avc->policydb,
2686cd6a6acSopenharmony_ci			   load_booleans, NULL);
2696cd6a6acSopenharmony_ci
2706cd6a6acSopenharmony_ci	/* Initialize the sidtab for subsequent use by sepol_context_to_sid
2716cd6a6acSopenharmony_ci	   and sepol_compute_av_reason. */
2726cd6a6acSopenharmony_ci	rc = sepol_sidtab_init(&sidtab);
2736cd6a6acSopenharmony_ci	if (rc < 0) {
2746cd6a6acSopenharmony_ci		PyErr_SetString( PyExc_RuntimeError, "unable to init sidtab\n");
2756cd6a6acSopenharmony_ci		goto err;
2766cd6a6acSopenharmony_ci	}
2776cd6a6acSopenharmony_ci	sepol_set_sidtab(&sidtab);
2786cd6a6acSopenharmony_ci	return 0;
2796cd6a6acSopenharmony_ci
2806cd6a6acSopenharmony_cierr:
2816cd6a6acSopenharmony_ci	if (boollist)
2826cd6a6acSopenharmony_ci		free(boollist);
2836cd6a6acSopenharmony_ci	if (avc){
2846cd6a6acSopenharmony_ci		if (avc->handle)
2856cd6a6acSopenharmony_ci			sepol_handle_destroy(avc->handle);
2866cd6a6acSopenharmony_ci		if (avc->policydb)
2876cd6a6acSopenharmony_ci			sepol_policydb_free(avc->policydb);
2886cd6a6acSopenharmony_ci		free(avc);
2896cd6a6acSopenharmony_ci	}
2906cd6a6acSopenharmony_ci	if (pf)
2916cd6a6acSopenharmony_ci		sepol_policy_file_free(pf);
2926cd6a6acSopenharmony_ci	if (fp)
2936cd6a6acSopenharmony_ci		fclose(fp);
2946cd6a6acSopenharmony_ci	return 1;
2956cd6a6acSopenharmony_ci}
2966cd6a6acSopenharmony_ci
2976cd6a6acSopenharmony_cistatic PyObject *init(PyObject *self __attribute__((unused)), PyObject *args) {
2986cd6a6acSopenharmony_ci  int result;
2996cd6a6acSopenharmony_ci  char *init_path = NULL;
3006cd6a6acSopenharmony_ci  if (avc) {
3016cd6a6acSopenharmony_ci	  PyErr_SetString( PyExc_RuntimeError, "init called multiple times");
3026cd6a6acSopenharmony_ci	  return NULL;
3036cd6a6acSopenharmony_ci  }
3046cd6a6acSopenharmony_ci  if (!PyArg_ParseTuple(args,(char *)"|s:policy_init",&init_path))
3056cd6a6acSopenharmony_ci    return NULL;
3066cd6a6acSopenharmony_ci  result = __policy_init(init_path);
3076cd6a6acSopenharmony_ci  return Py_BuildValue("i", result);
3086cd6a6acSopenharmony_ci}
3096cd6a6acSopenharmony_ci
3106cd6a6acSopenharmony_ci#define RETURN(X) \
3116cd6a6acSopenharmony_ci	{ \
3126cd6a6acSopenharmony_ci		return Py_BuildValue("iO", (X), Py_None);	\
3136cd6a6acSopenharmony_ci	}
3146cd6a6acSopenharmony_ci
3156cd6a6acSopenharmony_cistatic PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args) {
3166cd6a6acSopenharmony_ci	char *reason_buf = NULL;
3176cd6a6acSopenharmony_ci	char * scon;
3186cd6a6acSopenharmony_ci	char * tcon;
3196cd6a6acSopenharmony_ci	char *tclassstr;
3206cd6a6acSopenharmony_ci	PyObject *listObj;
3216cd6a6acSopenharmony_ci	PyObject *strObj;
3226cd6a6acSopenharmony_ci	int numlines;
3236cd6a6acSopenharmony_ci	struct boolean_t *bools;
3246cd6a6acSopenharmony_ci	unsigned int reason;
3256cd6a6acSopenharmony_ci	sepol_security_id_t ssid, tsid;
3266cd6a6acSopenharmony_ci	sepol_security_class_t tclass;
3276cd6a6acSopenharmony_ci	sepol_access_vector_t perm, av;
3286cd6a6acSopenharmony_ci	struct sepol_av_decision avd;
3296cd6a6acSopenharmony_ci	int rc;
3306cd6a6acSopenharmony_ci	int i = 0;
3316cd6a6acSopenharmony_ci
3326cd6a6acSopenharmony_ci	if (!PyArg_ParseTuple(args,(char *)"sssO!:audit2why",&scon,&tcon,&tclassstr,&PyList_Type, &listObj))
3336cd6a6acSopenharmony_ci		return NULL;
3346cd6a6acSopenharmony_ci
3356cd6a6acSopenharmony_ci	/* get the number of lines passed to us */
3366cd6a6acSopenharmony_ci	numlines = PyList_Size(listObj);
3376cd6a6acSopenharmony_ci
3386cd6a6acSopenharmony_ci	/* should raise an error here. */
3396cd6a6acSopenharmony_ci	if (numlines < 0)	return NULL; /* Not a list */
3406cd6a6acSopenharmony_ci
3416cd6a6acSopenharmony_ci	if (!avc)
3426cd6a6acSopenharmony_ci		RETURN(NOPOLICY)
3436cd6a6acSopenharmony_ci
3446cd6a6acSopenharmony_ci	rc = sepol_context_to_sid(scon, strlen(scon) + 1, &ssid);
3456cd6a6acSopenharmony_ci	if (rc < 0)
3466cd6a6acSopenharmony_ci		RETURN(BADSCON)
3476cd6a6acSopenharmony_ci
3486cd6a6acSopenharmony_ci	rc = sepol_context_to_sid(tcon, strlen(tcon) + 1, &tsid);
3496cd6a6acSopenharmony_ci	if (rc < 0)
3506cd6a6acSopenharmony_ci		RETURN(BADTCON)
3516cd6a6acSopenharmony_ci
3526cd6a6acSopenharmony_ci	rc = sepol_string_to_security_class(tclassstr, &tclass);
3536cd6a6acSopenharmony_ci	if (rc < 0)
3546cd6a6acSopenharmony_ci		RETURN(BADTCLASS)
3556cd6a6acSopenharmony_ci
3566cd6a6acSopenharmony_ci	/* Convert the permission list to an AV. */
3576cd6a6acSopenharmony_ci	av = 0;
3586cd6a6acSopenharmony_ci
3596cd6a6acSopenharmony_ci	/* iterate over items of the list, grabbing strings, and parsing
3606cd6a6acSopenharmony_ci	   for numbers */
3616cd6a6acSopenharmony_ci	for (i = 0; i < numlines; i++){
3626cd6a6acSopenharmony_ci		const char *permstr;
3636cd6a6acSopenharmony_ci
3646cd6a6acSopenharmony_ci		/* grab the string object from the next element of the list */
3656cd6a6acSopenharmony_ci		strObj = PyList_GetItem(listObj, i); /* Can't fail */
3666cd6a6acSopenharmony_ci
3676cd6a6acSopenharmony_ci		/* make it a string */
3686cd6a6acSopenharmony_ci#if PY_MAJOR_VERSION >= 3
3696cd6a6acSopenharmony_ci		permstr = _PyUnicode_AsString( strObj );
3706cd6a6acSopenharmony_ci#else
3716cd6a6acSopenharmony_ci		permstr = PyString_AsString( strObj );
3726cd6a6acSopenharmony_ci#endif
3736cd6a6acSopenharmony_ci
3746cd6a6acSopenharmony_ci		rc = sepol_string_to_av_perm(tclass, permstr, &perm);
3756cd6a6acSopenharmony_ci		if (rc < 0)
3766cd6a6acSopenharmony_ci			RETURN(BADPERM)
3776cd6a6acSopenharmony_ci
3786cd6a6acSopenharmony_ci		av |= perm;
3796cd6a6acSopenharmony_ci	}
3806cd6a6acSopenharmony_ci
3816cd6a6acSopenharmony_ci	/* Reproduce the computation. */
3826cd6a6acSopenharmony_ci	rc = sepol_compute_av_reason_buffer(ssid, tsid, tclass, av, &avd, &reason, &reason_buf, 0);
3836cd6a6acSopenharmony_ci	if (rc < 0)
3846cd6a6acSopenharmony_ci		RETURN(BADCOMPUTE)
3856cd6a6acSopenharmony_ci
3866cd6a6acSopenharmony_ci	if (!reason)
3876cd6a6acSopenharmony_ci		RETURN(ALLOW)
3886cd6a6acSopenharmony_ci
3896cd6a6acSopenharmony_ci	if (reason & SEPOL_COMPUTEAV_TE) {
3906cd6a6acSopenharmony_ci		avc->ssid = ssid;
3916cd6a6acSopenharmony_ci		avc->tsid = tsid;
3926cd6a6acSopenharmony_ci		avc->tclass = tclass;
3936cd6a6acSopenharmony_ci		avc->av = av;
3946cd6a6acSopenharmony_ci		if (check_booleans(&bools) == 0) {
3956cd6a6acSopenharmony_ci			if (av & ~avd.auditdeny) {
3966cd6a6acSopenharmony_ci				RETURN(DONTAUDIT)
3976cd6a6acSopenharmony_ci			} else {
3986cd6a6acSopenharmony_ci				RETURN(TERULE)
3996cd6a6acSopenharmony_ci			}
4006cd6a6acSopenharmony_ci		} else {
4016cd6a6acSopenharmony_ci			PyObject *outboollist;
4026cd6a6acSopenharmony_ci			struct boolean_t *b = bools;
4036cd6a6acSopenharmony_ci			int len = 0;
4046cd6a6acSopenharmony_ci			while (b->name) {
4056cd6a6acSopenharmony_ci				len++; b++;
4066cd6a6acSopenharmony_ci			}
4076cd6a6acSopenharmony_ci			b = bools;
4086cd6a6acSopenharmony_ci			outboollist = PyList_New(len);
4096cd6a6acSopenharmony_ci			len = 0;
4106cd6a6acSopenharmony_ci			while(b->name) {
4116cd6a6acSopenharmony_ci				PyObject *bool_ = Py_BuildValue("(si)", b->name, b->active);
4126cd6a6acSopenharmony_ci				PyList_SetItem(outboollist, len++, bool_);
4136cd6a6acSopenharmony_ci				b++;
4146cd6a6acSopenharmony_ci			}
4156cd6a6acSopenharmony_ci			free(bools);
4166cd6a6acSopenharmony_ci			/* 'N' steals the reference to outboollist */
4176cd6a6acSopenharmony_ci			return Py_BuildValue("iN", BOOLEAN, outboollist);
4186cd6a6acSopenharmony_ci		}
4196cd6a6acSopenharmony_ci	}
4206cd6a6acSopenharmony_ci
4216cd6a6acSopenharmony_ci	if (reason & SEPOL_COMPUTEAV_CONS) {
4226cd6a6acSopenharmony_ci		if (reason_buf) {
4236cd6a6acSopenharmony_ci			PyObject *result = NULL;
4246cd6a6acSopenharmony_ci			result = Py_BuildValue("is", CONSTRAINT, reason_buf);
4256cd6a6acSopenharmony_ci			free(reason_buf);
4266cd6a6acSopenharmony_ci			return result;
4276cd6a6acSopenharmony_ci		}
4286cd6a6acSopenharmony_ci		RETURN(CONSTRAINT)
4296cd6a6acSopenharmony_ci	}
4306cd6a6acSopenharmony_ci
4316cd6a6acSopenharmony_ci	if (reason & SEPOL_COMPUTEAV_RBAC)
4326cd6a6acSopenharmony_ci		RETURN(RBAC)
4336cd6a6acSopenharmony_ci
4346cd6a6acSopenharmony_ci	if (reason & SEPOL_COMPUTEAV_BOUNDS)
4356cd6a6acSopenharmony_ci		RETURN(BOUNDS)
4366cd6a6acSopenharmony_ci
4376cd6a6acSopenharmony_ci        RETURN(BADCOMPUTE)
4386cd6a6acSopenharmony_ci}
4396cd6a6acSopenharmony_ci
4406cd6a6acSopenharmony_cistatic PyMethodDef audit2whyMethods[] = {
4416cd6a6acSopenharmony_ci    {"init",  init, METH_VARARGS,
4426cd6a6acSopenharmony_ci     "Initialize policy database."},
4436cd6a6acSopenharmony_ci    {"analyze",  analyze, METH_VARARGS,
4446cd6a6acSopenharmony_ci     "Analyze AVC."},
4456cd6a6acSopenharmony_ci    {"finish",  finish, METH_VARARGS,
4466cd6a6acSopenharmony_ci     "Finish using policy, free memory."},
4476cd6a6acSopenharmony_ci    {NULL, NULL, 0, NULL}        /* Sentinel */
4486cd6a6acSopenharmony_ci};
4496cd6a6acSopenharmony_ci
4506cd6a6acSopenharmony_ci#if PY_MAJOR_VERSION >= 3
4516cd6a6acSopenharmony_ci/* Module-initialization logic specific to Python 3 */
4526cd6a6acSopenharmony_cistatic struct PyModuleDef moduledef = {
4536cd6a6acSopenharmony_ci	PyModuleDef_HEAD_INIT,
4546cd6a6acSopenharmony_ci	"audit2why",
4556cd6a6acSopenharmony_ci	NULL,
4566cd6a6acSopenharmony_ci	0,
4576cd6a6acSopenharmony_ci	audit2whyMethods,
4586cd6a6acSopenharmony_ci	NULL,
4596cd6a6acSopenharmony_ci	NULL,
4606cd6a6acSopenharmony_ci	NULL,
4616cd6a6acSopenharmony_ci	NULL
4626cd6a6acSopenharmony_ci};
4636cd6a6acSopenharmony_ci
4646cd6a6acSopenharmony_ciPyMODINIT_FUNC PyInit_audit2why(void); /* silence -Wmissing-prototypes */
4656cd6a6acSopenharmony_ciPyMODINIT_FUNC PyInit_audit2why(void)
4666cd6a6acSopenharmony_ci#else
4676cd6a6acSopenharmony_ciPyMODINIT_FUNC initaudit2why(void); /* silence -Wmissing-prototypes */
4686cd6a6acSopenharmony_ciPyMODINIT_FUNC initaudit2why(void)
4696cd6a6acSopenharmony_ci#endif
4706cd6a6acSopenharmony_ci{
4716cd6a6acSopenharmony_ci	PyObject *m;
4726cd6a6acSopenharmony_ci#if PY_MAJOR_VERSION >= 3
4736cd6a6acSopenharmony_ci	m = PyModule_Create(&moduledef);
4746cd6a6acSopenharmony_ci	if (m == NULL) {
4756cd6a6acSopenharmony_ci		return NULL;
4766cd6a6acSopenharmony_ci	}
4776cd6a6acSopenharmony_ci#else
4786cd6a6acSopenharmony_ci	m  = Py_InitModule("audit2why", audit2whyMethods);
4796cd6a6acSopenharmony_ci#endif
4806cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"UNKNOWN", UNKNOWN);
4816cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"BADSCON", BADSCON);
4826cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"BADTCON", BADTCON);
4836cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"BADTCLASS", BADTCLASS);
4846cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"BADPERM", BADPERM);
4856cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"BADCOMPUTE", BADCOMPUTE);
4866cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"NOPOLICY", NOPOLICY);
4876cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"ALLOW", ALLOW);
4886cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"DONTAUDIT", DONTAUDIT);
4896cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"TERULE", TERULE);
4906cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"BOOLEAN", BOOLEAN);
4916cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"CONSTRAINT", CONSTRAINT);
4926cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"RBAC", RBAC);
4936cd6a6acSopenharmony_ci	PyModule_AddIntConstant(m,"BOUNDS", BOUNDS);
4946cd6a6acSopenharmony_ci
4956cd6a6acSopenharmony_ci#if PY_MAJOR_VERSION >= 3
4966cd6a6acSopenharmony_ci	return m;
4976cd6a6acSopenharmony_ci#endif
4986cd6a6acSopenharmony_ci}
499