Home | History | Annotate | Download | only in sepolicy
      1 // Author: Thomas Liu <tliu (at) redhat.com>
      2 
      3 /**
      4  *  @file
      5  *  Python bindings used to search TE rules.
      6  *
      7  *  @author Thomas Liu  <tliu (at) redhat.com>
      8  *  @author Dan Walsh  <dwalsh (at) redhat.com>
      9  *  Copyright (C) 2012-2013 Red Hat, inc
     10  *
     11  *  Sections copied from sesearch.c in setools package
     12  *  @author Frank Mayer  mayerf (at) tresys.com
     13  *  @author Jeremy A. Mowery jmowery (at) tresys.com
     14  *  @author Paul Rosenfeld  prosenfeld (at) tresys.com
     15  *  Copyright (C) 2003-2008 Tresys Technology, LLC
     16  *
     17  *  This program is free software; you can redistribute it and/or modify
     18  *  it under the terms of the GNU General Public License as published by
     19  *  the Free Software Foundation; either version 2 of the License, or
     20  *  (at your option) any later version.
     21  *
     22  *  This program is distributed in the hope that it will be useful,
     23  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     24  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     25  *  GNU General Public License for more details.
     26  *
     27  *  You should have received a copy of the GNU General Public License
     28  *  along with this program; if not, write to the Free Software
     29  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     30  */
     31 
     32 /**
     33  * This is a modified version of sesearch to be used as part of a sepython library for
     34  * Python bindings.
     35  */
     36 
     37 #include "common.h"
     38 #include "policy.h"
     39 
     40 /* libapol */
     41 #include <apol/policy-query.h>
     42 #include <apol/render.h>
     43 #include <apol/util.h>
     44 #include <apol/vector.h>
     45 
     46 /* libqpol*/
     47 #include <qpol/policy.h>
     48 #include <qpol/policy_extend.h>
     49 #include <qpol/syn_rule_query.h>
     50 #include <qpol/util.h>
     51 
     52 /* other */
     53 #include <errno.h>
     54 #include <stdlib.h>
     55 #include <stdio.h>
     56 #include <assert.h>
     57 #include <getopt.h>
     58 #include <string.h>
     59 #include <stdbool.h>
     60 
     61 #define COPYRIGHT_INFO "Copyright (C) 2012 Red Hat, Inc, Tresys Technology, LLC"
     62 
     63 enum opt_values
     64 {
     65 	RULE_NEVERALLOW = 256, RULE_AUDIT, RULE_AUDITALLOW, RULE_DONTAUDIT,
     66 	RULE_ROLE_ALLOW, RULE_ROLE_TRANS, RULE_RANGE_TRANS, RULE_ALL,
     67 	EXPR_ROLE_SOURCE, EXPR_ROLE_TARGET
     68 };
     69 
     70 ;
     71 
     72 typedef struct options
     73 {
     74 	char *src_name;
     75 	char *tgt_name;
     76 	char *src_role_name;
     77 	char *tgt_role_name;
     78 	char *class_name;
     79 	char *permlist;
     80 	char *bool_name;
     81 	apol_vector_t *class_vector;
     82 	bool all;
     83 	bool lineno;
     84 	bool semantic;
     85 	bool indirect;
     86 	bool allow;
     87 	bool nallow;
     88 	bool auditallow;
     89 	bool dontaudit;
     90 	bool type;
     91 	bool rtrans;
     92 	bool role_allow;
     93 	bool role_trans;
     94 	bool useregex;
     95 	bool show_cond;
     96 	apol_vector_t *perm_vector;
     97 } options_t;
     98 
     99 static int py_tuple_insert_obj(PyObject *tuple, int pos, PyObject *obj)
    100 {
    101 	int rt;
    102 	if (!obj) return -1;
    103 	rt = PyTuple_SetItem(tuple, pos, obj);
    104 	return rt;
    105 }
    106 
    107 static int perform_ra_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v)
    108 {
    109 	apol_role_allow_query_t *raq = NULL;
    110 	int error = 0;
    111 
    112 	if (!policy || !opt || !v) {
    113 		ERR(policy, "%s", strerror(EINVAL));
    114 		errno = EINVAL;
    115 		return -1;
    116 	}
    117 
    118 	if (!opt->role_allow && !opt->all) {
    119 		*v = NULL;
    120 		return 0;	       /* no search to do */
    121 	}
    122 
    123 	raq = apol_role_allow_query_create();
    124 	if (!raq) {
    125 		ERR(policy, "%s", strerror(ENOMEM));
    126 		errno = ENOMEM;
    127 		return -1;
    128 	}
    129 
    130 	apol_role_allow_query_set_regex(policy, raq, opt->useregex);
    131 	if (opt->src_role_name) {
    132 		if (apol_role_allow_query_set_source(policy, raq, opt->src_role_name)) {
    133 			error = errno;
    134 			goto err;
    135 		}
    136 	}
    137 	if (opt->tgt_role_name)
    138 		if (apol_role_allow_query_set_target(policy, raq, opt->tgt_role_name)) {
    139 			error = errno;
    140 			goto err;
    141 		}
    142 
    143 	if (apol_role_allow_get_by_query(policy, raq, v)) {
    144 		error = errno;
    145 		goto err;
    146 	}
    147 	apol_role_allow_query_destroy(&raq);
    148 	return 0;
    149 
    150       err:
    151 	apol_vector_destroy(v);
    152 	apol_role_allow_query_destroy(&raq);
    153 	ERR(policy, "%s", strerror(error));
    154 	errno = error;
    155 	return -1;
    156 }
    157 
    158 static PyObject* get_ra_results(const apol_policy_t * policy, const apol_vector_t * v, PyObject *output)
    159 {
    160 	size_t i, num_rules = 0;
    161 	qpol_policy_t *q;
    162 	const qpol_role_allow_t *rule = NULL;
    163 	const char *tmp;
    164 	PyObject *obj, *dict=NULL;
    165 	const qpol_role_t *role = NULL;
    166 	int error = 0;
    167 	errno = EINVAL;
    168 	int rt;
    169 
    170 	if (!policy || !v) {
    171 		errno = EINVAL;
    172 		goto err;
    173 	}
    174 
    175 	if (!(num_rules = apol_vector_get_size(v)))
    176 		return NULL;
    177 
    178 	q = apol_policy_get_qpol(policy);
    179 
    180 	for (i = 0; i < num_rules; i++) {
    181 		dict = PyDict_New();
    182 		if (!dict) goto err;
    183 		if (!(rule = apol_vector_get_element(v, i)))
    184 			goto err;
    185 
    186 		if (qpol_role_allow_get_source_role(q, rule, &role)) {
    187 			goto err;
    188 		}
    189 		if (qpol_role_get_name(q, role, &tmp)) {
    190 			goto err;
    191 		}
    192 		obj = PyString_FromString(tmp);
    193 		if (py_insert_obj(dict, "source", obj))
    194 			goto err;
    195 
    196 		if (qpol_role_allow_get_target_role(q, rule, &role)) {
    197 			goto err;
    198 		}
    199 		if (qpol_role_get_name(q, role, &tmp)) {
    200 			goto err;
    201 		}
    202 		obj = PyString_FromString(tmp);
    203 		if (py_insert_obj(dict, "target", obj))
    204 			goto err;
    205 
    206 		rt = py_append_obj(output, dict);
    207 		if (rt) goto err;
    208 		py_decref(dict); dict=NULL;
    209 	}
    210 	goto cleanup;
    211 err:
    212 	error = errno;
    213 	PyErr_SetString(PyExc_RuntimeError,strerror(error));
    214 	py_decref(dict);
    215 
    216 cleanup:
    217 	errno = error;
    218 	return output;
    219 }
    220 
    221 static int perform_te_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v)
    222 {
    223 	apol_terule_query_t *teq = NULL;
    224 	unsigned int rules = 0;
    225 	int error = 0;
    226 	size_t i;
    227 
    228 	if (!policy || !opt || !v) {
    229 		PyErr_SetString(PyExc_RuntimeError,strerror(EINVAL));
    230 		errno = EINVAL;
    231 		return -1;
    232 	}
    233 
    234 	if (opt->all || opt->type) {
    235 		rules = (QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_CHANGE | QPOL_RULE_TYPE_MEMBER);
    236 	} else {
    237 		*v = NULL;
    238 		return 0;	       /* no search to do */
    239 	}
    240 
    241 	teq = apol_terule_query_create();
    242 	if (!teq) {
    243 		PyErr_SetString(PyExc_RuntimeError,strerror(ENOMEM));
    244 		errno = ENOMEM;
    245 		return -1;
    246 	}
    247 
    248 	apol_terule_query_set_rules(policy, teq, rules);
    249 	apol_terule_query_set_regex(policy, teq, opt->useregex);
    250 
    251 	if (opt->src_name)
    252 		apol_terule_query_set_source(policy, teq, opt->src_name, opt->indirect);
    253 	if (opt->tgt_name)
    254 		apol_terule_query_set_target(policy, teq, opt->tgt_name, opt->indirect);
    255 	if (opt->bool_name)
    256 		apol_terule_query_set_bool(policy, teq, opt->bool_name);
    257 	if (opt->class_name) {
    258 		if (opt->class_vector == NULL) {
    259 			if (apol_terule_query_append_class(policy, teq, opt->class_name)) {
    260 				error = errno;
    261 				goto err;
    262 			}
    263 		} else {
    264 			for (i = 0; i < apol_vector_get_size(opt->class_vector); ++i) {
    265 				char *class_name;
    266 				class_name = apol_vector_get_element(opt->class_vector, i);
    267 				if (!class_name)
    268 					continue;
    269 				if (apol_terule_query_append_class(policy, teq, class_name)) {
    270 					error = errno;
    271 					goto err;
    272 				}
    273 			}
    274 		}
    275 	}
    276 
    277 	if (!(opt->semantic) && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) {
    278 		if (apol_syn_terule_get_by_query(policy, teq, v)) {
    279 			goto err;
    280 		}
    281 	} else {
    282 		if (apol_terule_get_by_query(policy, teq, v)) {
    283 			goto err;
    284 		}
    285 	}
    286 
    287 	apol_terule_query_destroy(&teq);
    288 	return 0;
    289 
    290 err:
    291 	error = errno;
    292 	PyErr_SetString(PyExc_RuntimeError,strerror(error));
    293 	apol_vector_destroy(v);
    294 	apol_terule_query_destroy(&teq);
    295 	errno = error;
    296 	return -1;
    297 }
    298 
    299 static PyObject* get_bool(const qpol_policy_t *q, const qpol_cond_t * cond, int enabled)
    300 {
    301 	qpol_iterator_t *iter = NULL;
    302 	qpol_cond_expr_node_t *expr = NULL;
    303 	char *tmp = NULL;
    304 	const char *bool_name = NULL;
    305 	int error = 0;
    306 	uint32_t expr_type = 0;
    307 	qpol_bool_t *cond_bool = NULL;
    308 	PyObject *obj, *tuple = NULL;
    309 	PyObject *boollist = NULL;
    310 
    311 	if (!q || !cond) {
    312 		errno = EINVAL;
    313 		return NULL;
    314 	}
    315 	if (qpol_cond_get_expr_node_iter(q, cond, &iter) < 0) {
    316 		goto err;
    317 	}
    318 
    319 	boollist = PyList_New(0);
    320 	if (! boollist) goto err;
    321 
    322 	for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
    323 		if (qpol_iterator_get_item(iter, (void **)&expr)) {
    324 			goto err;
    325 		}
    326 		if (qpol_cond_expr_node_get_expr_type(q, expr, &expr_type)) {
    327 			goto err;
    328 		}
    329 		if (expr_type != QPOL_COND_EXPR_BOOL) {
    330 			obj = PyString_FromString(apol_cond_expr_type_to_str(expr_type));
    331 			if (!obj) goto err;
    332 			if (py_append_obj(boollist, obj))
    333 				goto err;
    334 		} else {
    335 			tuple = PyTuple_New(2);
    336 			if (!tuple) goto err;
    337 
    338 			if (qpol_cond_expr_node_get_bool(q, expr, &cond_bool)) {
    339 				goto err;
    340 			}
    341 			if (qpol_bool_get_name(q, cond_bool, &bool_name)) {
    342 				goto err;
    343 			}
    344 			obj = PyString_FromString(bool_name);
    345 			if (py_tuple_insert_obj(tuple, 0, obj))
    346 				goto err;
    347 			obj = PyBool_FromLong(enabled);
    348 			if (py_tuple_insert_obj(tuple, 1, obj))
    349 				goto err;
    350 			if (py_append_obj(boollist, tuple))
    351 				goto err;
    352 			tuple=NULL;
    353 		}
    354 	}
    355 
    356 	qpol_iterator_destroy(&iter);
    357 	return boollist;
    358 
    359       err:
    360 	error = errno;
    361 	qpol_iterator_destroy(&iter);
    362 	py_decref(tuple);
    363 	py_decref(boollist);
    364 	free(tmp);
    365 	errno = error;
    366 	return NULL;
    367 }
    368 
    369 static PyObject* get_te_results(const apol_policy_t * policy, const apol_vector_t * v, PyObject *output)
    370 {
    371 	int error = 0;
    372 	int rt = 0;
    373 	PyObject *obj, *dict=NULL, *tuple = NULL;
    374 	qpol_policy_t *q;
    375 	uint32_t rule_type = 0;
    376 	const qpol_type_t *type;
    377 	size_t i, num_rules = 0;
    378 	const qpol_terule_t *rule = NULL;
    379 	char *tmp = NULL, *rule_str = NULL, *expr = NULL;
    380 	const qpol_cond_t *cond = NULL;
    381 	uint32_t enabled = 0;
    382 	const char *tmp_name;
    383 	const qpol_class_t *obj_class = NULL;
    384 
    385 	if (!policy || !v) {
    386 		errno = EINVAL;
    387 		goto err;
    388 	}
    389 
    390 	if (!(num_rules = apol_vector_get_size(v)))
    391 		return NULL;
    392 
    393 	q = apol_policy_get_qpol(policy);
    394 
    395 	for (i = 0; i < num_rules; i++) {
    396 		dict = PyDict_New();
    397 		if (!dict) goto err;
    398 		if (!(rule = apol_vector_get_element(v, i)))
    399 			goto err;
    400 		if (qpol_terule_get_cond(q, rule, &cond))
    401 			goto err;
    402 		if (qpol_terule_get_is_enabled(q, rule, &enabled))
    403 			goto err;
    404 
    405 		if (cond) {
    406 			obj = get_bool(q, cond, enabled);
    407 			if (!obj) goto err;
    408 			rt = PyDict_SetItemString(dict, "boolean", obj);
    409 			py_decref(obj);
    410 		}
    411 
    412 		if (qpol_terule_get_rule_type(q, rule, &rule_type))
    413 			goto err;
    414 
    415 		if (!(rule_type &= (QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_CHANGE | QPOL_RULE_TYPE_MEMBER))) {
    416 			PyErr_SetString(PyExc_RuntimeError,"Invalid TE rule type");
    417 			errno = EINVAL;
    418 			goto err;
    419 		}
    420 		if (!(tmp_name = apol_rule_type_to_str(rule_type))) {
    421 			PyErr_SetString(PyExc_RuntimeError, "Could not get TE rule type's string");
    422 			errno = EINVAL;
    423 			goto err;
    424 		}
    425 
    426 		if (py_insert_string(dict, "type", tmp_name))
    427 			goto err;
    428 
    429 		if (qpol_terule_get_source_type(q, rule, &type))
    430 			goto err;
    431 		if (qpol_type_get_name(q, type, &tmp_name))
    432 			goto err;
    433 		if (py_insert_string(dict, "source", tmp_name))
    434 			goto err;
    435 
    436 		if (qpol_terule_get_target_type(q, rule, &type))
    437 			goto err;
    438 		if (qpol_type_get_name(q, type, &tmp_name))
    439 			goto err;
    440 		if (py_insert_string(dict, "target", tmp_name))
    441 			goto err;
    442 
    443 		if (qpol_terule_get_object_class(q, rule, &obj_class))
    444 			goto err;
    445 		if (qpol_class_get_name(q, obj_class, &tmp_name))
    446 			goto err;
    447 		if (py_insert_string(dict, "class", tmp_name))
    448 			goto err;
    449 
    450 		if (qpol_terule_get_default_type(q, rule, &type))
    451 			goto err;
    452 		if (qpol_type_get_name(q, type, &tmp_name))
    453 			goto err;
    454 		if (py_insert_string(dict, "transtype", tmp_name))
    455 			goto err;
    456 
    457 		rt = py_append_obj(output, dict);
    458 		dict = NULL;
    459 		if(rt) goto err;
    460 
    461 		free(rule_str);	rule_str = NULL;
    462 		free(expr); expr = NULL;
    463 	}
    464 	goto cleanup;
    465 
    466 err:
    467 	error = errno;
    468 	py_decref(dict);
    469 	py_decref(tuple);
    470 	PyErr_SetString(PyExc_RuntimeError,strerror(error));
    471 cleanup:
    472 	free(tmp);
    473 	free(rule_str);
    474 	free(expr);
    475 	errno = error;
    476 	return output;
    477 }
    478 
    479 static int perform_ft_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v)
    480 {
    481 	apol_filename_trans_query_t *ftq = NULL;
    482 	size_t i;
    483 	int error = 0;
    484 
    485 	if (!policy || !opt || !v) {
    486 		PyErr_SetString(PyExc_RuntimeError,strerror(EINVAL));
    487 		errno = EINVAL;
    488 		return -1;
    489 	}
    490 
    491 	if (!opt->type && !opt->all) {
    492 		*v = NULL;
    493 		return 0;	       /* no search to do */
    494 	}
    495 
    496 	ftq = apol_filename_trans_query_create();
    497 	if (!ftq) {
    498 		PyErr_SetString(PyExc_RuntimeError,strerror(ENOMEM));
    499 		errno = ENOMEM;
    500 		return -1;
    501 	}
    502 
    503 	apol_filename_trans_query_set_regex(policy, ftq, opt->useregex);
    504 	if (opt->src_name) {
    505 		if (apol_filename_trans_query_set_source(policy, ftq, opt->src_name, opt->indirect)) {
    506 			goto err;
    507 		}
    508 	}
    509 
    510 	if (opt->tgt_name) {
    511 		if (apol_filename_trans_query_set_target(policy, ftq, opt->tgt_name, opt->indirect)) {
    512 			goto err;
    513 		}
    514 	}
    515 	if (opt->class_name) {
    516 		if (opt->class_vector == NULL) {
    517 			if (apol_filename_trans_query_append_class(policy, ftq, opt->class_name)) {
    518 				goto err;
    519 			}
    520 		} else {
    521 			for (i = 0; i < apol_vector_get_size(opt->class_vector); ++i) {
    522 				char *class_name;
    523 				class_name = apol_vector_get_element(opt->class_vector, i);
    524 				if (!class_name)
    525 					continue;
    526 				if (apol_filename_trans_query_append_class(policy, ftq, class_name)) {
    527 					goto err;
    528 				}
    529 			}
    530 		}
    531 	}
    532 
    533 	if (apol_filename_trans_get_by_query(policy, ftq, v))
    534 		goto err;
    535 
    536 	apol_filename_trans_query_destroy(&ftq);
    537 	return 0;
    538 
    539 err:
    540 	error = errno;
    541 	PyErr_SetString(PyExc_RuntimeError,strerror(errno));
    542 	apol_vector_destroy(v);
    543 	apol_filename_trans_query_destroy(&ftq);
    544 	errno = error;
    545 	return -1;
    546 }
    547 
    548 static PyObject* get_ft_results(const apol_policy_t * policy, const apol_vector_t * v, PyObject *list)
    549 {
    550 	PyObject *dict = NULL;
    551 	size_t i, num_filename_trans = 0;
    552 	const char *tmp_name;
    553 	int error = 0;
    554 	int rt;
    555 	const qpol_filename_trans_t *filename_trans = NULL;
    556 	const qpol_class_t *obj_class = NULL;
    557 	char *tmp = NULL, *filename_trans_str = NULL, *expr = NULL;
    558 	qpol_policy_t *q;
    559 	const qpol_type_t *type = NULL;
    560 
    561 	if (!policy || !v) {
    562 		errno = EINVAL;
    563 		goto err;
    564 	}
    565 
    566 	if (!(num_filename_trans = apol_vector_get_size(v)))
    567 		return NULL;
    568 
    569 	q = apol_policy_get_qpol(policy);
    570 
    571 	for (i = 0; i < num_filename_trans; i++) {
    572 		if (!(filename_trans = apol_vector_get_element(v, i)))
    573 			goto err;
    574 
    575 		dict = PyDict_New();
    576 		if (!dict) goto err;
    577 
    578 		if (py_insert_string(dict, "type", "type_transition"))
    579 			goto err;
    580 
    581 		/* source type */
    582 		if (qpol_filename_trans_get_source_type(q, filename_trans, &type)) {
    583 			goto err;
    584 		}
    585 		if (qpol_type_get_name(q, type, &tmp_name)) {
    586 			goto err;
    587 		}
    588 
    589 		if (py_insert_string(dict, "source", tmp_name))
    590 			goto err;
    591 
    592 		if (qpol_filename_trans_get_target_type(q, filename_trans, &type))
    593 			goto err;
    594 
    595 		if (qpol_type_get_name(q, type, &tmp_name))
    596 			goto err;
    597 
    598 		if (py_insert_string(dict, "target", tmp_name))
    599 			goto err;
    600 
    601 		if (qpol_filename_trans_get_object_class(q, filename_trans, &obj_class))
    602 			goto err;
    603 
    604 		if (qpol_class_get_name(q, obj_class, &tmp_name))
    605 			goto err;
    606 
    607 		if (py_insert_string(dict, "class", tmp_name))
    608 			goto err;
    609 
    610 		if (qpol_filename_trans_get_default_type(q, filename_trans, &type))
    611 			goto err;
    612 		if (qpol_type_get_name(q, type, &tmp_name))
    613 			goto err;
    614 		if (py_insert_string(dict, "transtype", tmp_name))
    615 			goto err;
    616 
    617 		if (! qpol_filename_trans_get_filename(q, filename_trans, &tmp_name)) {
    618 			if (py_insert_string(dict, "filename", tmp_name))
    619 				goto err;
    620 		}
    621 
    622 		rt = py_append_obj(list, dict);
    623 		dict = NULL;
    624 		if (rt) goto err;
    625 
    626 		free(filename_trans_str); filename_trans_str = NULL;
    627 		free(expr); expr = NULL;
    628 	}
    629 	goto cleanup;
    630 
    631 err:
    632 	error = errno;
    633 	PyErr_SetString(PyExc_RuntimeError,strerror(errno));
    634 	py_decref(dict);
    635 cleanup:
    636 	free(tmp);
    637 	free(filename_trans_str);
    638 	free(expr);
    639 	errno = error;
    640 	return list;
    641 }
    642 
    643 static int perform_av_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v)
    644 {
    645 	apol_avrule_query_t *avq = NULL;
    646 	unsigned int rules = 0;
    647 	int error = 0;
    648 	char *tmp = NULL, *tok = NULL, *s = NULL;
    649 
    650 	if (!policy || !opt || !v) {
    651 		PyErr_SetString(PyExc_RuntimeError,strerror(EINVAL));
    652 		errno = EINVAL;
    653 		return -1;
    654 	}
    655 
    656 	if (!opt->all && !opt->allow && !opt->nallow && !opt->auditallow && !opt->dontaudit) {
    657 		*v = NULL;
    658 		return 0;	       /* no search to do */
    659 	}
    660 
    661 	avq = apol_avrule_query_create();
    662 	if (!avq) {
    663 		PyErr_SetString(PyExc_RuntimeError,strerror(ENOMEM));
    664 		errno = ENOMEM;
    665 		return -1;
    666 	}
    667 
    668 	if (opt->allow || opt->all)
    669 		rules |= QPOL_RULE_ALLOW;
    670 	if (opt->nallow || opt->all)	// Add this regardless of policy capabilities
    671 		rules |= QPOL_RULE_NEVERALLOW;
    672 	if (opt->auditallow || opt->all)
    673 		rules |= QPOL_RULE_AUDITALLOW;
    674 	if (opt->dontaudit || opt->all)
    675 		rules |= QPOL_RULE_DONTAUDIT;
    676 	if (rules != 0)	// Setting rules = 0 means you want all the rules
    677 		apol_avrule_query_set_rules(policy, avq, rules);
    678 	apol_avrule_query_set_regex(policy, avq, opt->useregex);
    679 	if (opt->src_name)
    680 		apol_avrule_query_set_source(policy, avq, opt->src_name, opt->indirect);
    681 	if (opt->tgt_name)
    682 		apol_avrule_query_set_target(policy, avq, opt->tgt_name, opt->indirect);
    683 	if (opt->bool_name)
    684 		apol_avrule_query_set_bool(policy, avq, opt->bool_name);
    685 	if (opt->class_name) {
    686 		if (opt->class_vector == NULL) {
    687 			if (apol_avrule_query_append_class(policy, avq, opt->class_name)) {
    688 				goto err;
    689 			}
    690 		} else {
    691 			size_t i;
    692 	    for (i = 0; i < apol_vector_get_size(opt->class_vector); ++i) {
    693 				char *class_name;
    694 				class_name = apol_vector_get_element(opt->class_vector, i);
    695 				if (!class_name)
    696 					continue;
    697 				if (apol_avrule_query_append_class(policy, avq, class_name)) {
    698 					goto err;
    699 				}
    700 			}
    701 		}
    702 	}
    703 
    704 	if (opt->permlist) {
    705 		tmp = strdup(opt->permlist);
    706 		for (tok = strtok(tmp, ","); tok; tok = strtok(NULL, ",")) {
    707 			if (apol_avrule_query_append_perm(policy, avq, tok)) {
    708 				goto err;
    709 			}
    710 			if ((s = strdup(tok)) == NULL || apol_vector_append(opt->perm_vector, s) < 0) {
    711 				goto err;
    712 			}
    713 			s = NULL;
    714 		}
    715 		free(tmp);
    716 		tmp = NULL;
    717 	}
    718 
    719 	if (!(opt->semantic) && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) {
    720 		if (apol_syn_avrule_get_by_query(policy, avq, v)) {
    721 			goto err;
    722 		}
    723 	} else {
    724 		if (apol_avrule_get_by_query(policy, avq, v)) {
    725 			goto err;
    726 		}
    727 	}
    728 
    729 	apol_avrule_query_destroy(&avq);
    730 	return 0;
    731 
    732 err:
    733 	error = errno;
    734 	PyErr_SetString(PyExc_RuntimeError,strerror(error));
    735 	apol_vector_destroy(v);
    736 	apol_avrule_query_destroy(&avq);
    737 	free(tmp);
    738 	free(s);
    739 	errno = error;
    740 	return -1;
    741 }
    742 
    743 static PyObject* get_av_results(const apol_policy_t * policy, const apol_vector_t * v, PyObject *output)
    744 {
    745 	PyObject *obj, *dict=NULL;
    746 	PyObject *permlist = NULL;
    747 	PyObject *boollist = NULL;
    748 	uint32_t rule_type = 0;
    749 	int rt;
    750 	int error = 0;
    751 	qpol_policy_t *q;
    752 	size_t i, num_rules = 0;
    753 	const qpol_avrule_t *rule = NULL;
    754 	char *tmp = NULL, *rule_str = NULL;
    755 	qpol_cond_expr_node_t *expr = NULL;
    756 	qpol_iterator_t *iter = NULL;
    757 	const qpol_cond_t *cond = NULL;
    758 	uint32_t enabled = 0;
    759 	const qpol_type_t *type;
    760 	const char *tmp_name;
    761 	const qpol_class_t *obj_class = NULL;
    762 
    763 	if (!policy || !v) {
    764 		errno = EINVAL;
    765 		goto err;
    766 	}
    767 
    768 	if (!(num_rules = apol_vector_get_size(v)))
    769 		return NULL;
    770 
    771 	q = apol_policy_get_qpol(policy);
    772 
    773 	for (i = 0; i < num_rules; i++) {
    774 		if (!(rule = apol_vector_get_element(v, i)))
    775 			goto err;
    776 
    777 		dict = PyDict_New();
    778 		if (!dict) goto err;
    779 
    780 		if (qpol_avrule_get_rule_type(q, rule, &rule_type))
    781 			goto err;
    782 
    783 		if (!(tmp_name = apol_rule_type_to_str(rule_type))) {
    784 			PyErr_SetString(PyExc_RuntimeError, "Could not get TE rule type's string");
    785 			errno = EINVAL;
    786 			goto err;
    787 		}
    788 
    789 		if (py_insert_string(dict, "type", tmp_name))
    790 			goto err;
    791 
    792 		if (qpol_avrule_get_source_type(q, rule, &type)) {
    793 			goto err;
    794 		}
    795 
    796 		if (qpol_type_get_name(q, type, &tmp_name)) {
    797 			goto err;
    798 		}
    799 
    800 		if (py_insert_string(dict, "source", tmp_name))
    801 			goto err;
    802 
    803 		if (qpol_avrule_get_target_type(q, rule, &type)) {
    804 			goto err;
    805 		}
    806 		if (qpol_type_get_name(q, type, &tmp_name)) {
    807 			goto err;
    808 		}
    809 
    810 		if (py_insert_string(dict, "target", tmp_name))
    811 			goto err;
    812 
    813 		if (qpol_avrule_get_object_class(q, rule, &obj_class)) {
    814 			goto err;
    815 		}
    816 		if (qpol_class_get_name(q, obj_class, &tmp_name)) {
    817 			goto err;
    818 		}
    819 
    820 		if (py_insert_string(dict, "class", tmp_name))
    821 			goto err;
    822 
    823 		if (qpol_avrule_get_perm_iter(q, rule, &iter)) {
    824 			goto err;
    825 		}
    826 
    827 		permlist = PyList_New(0);
    828 		if (! permlist) goto err;
    829 
    830 		for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
    831 			const char *perm_name = NULL;
    832 			if (qpol_iterator_get_item(iter, (void **)&perm_name))
    833 				goto err;
    834 			if (py_append_string(permlist, perm_name))
    835 				goto err;
    836 		}
    837 
    838 		rt = PyDict_SetItemString(dict, "permlist", permlist);
    839 		py_decref(permlist); permlist=NULL;
    840 		if (rt) goto err;
    841 
    842 		if (qpol_avrule_get_cond(q, rule, &cond))
    843 			goto err;
    844 		if (qpol_avrule_get_is_enabled(q, rule, &enabled))
    845 			goto err;
    846 
    847 		obj = PyBool_FromLong(enabled);
    848 		rt = PyDict_SetItemString(dict, "enabled", obj);
    849 		py_decref(obj);
    850 
    851 		if (cond) {
    852 			obj = get_bool(q, cond, enabled);
    853 			if (!obj) goto err;
    854 			rt = PyDict_SetItemString(dict, "boolean", obj);
    855 			py_decref(obj);
    856 		}
    857 
    858 		rt = py_append_obj(output, dict);
    859 		py_decref(dict); dict=NULL;
    860 		if (rt) goto err;
    861 
    862 		free(rule_str);	rule_str = NULL;
    863 		free(expr); expr = NULL;
    864 	}
    865 	goto cleanup;
    866 
    867 err:
    868 	error = errno;
    869 	PyErr_SetString(PyExc_RuntimeError,strerror(errno));
    870 	py_decref(dict);
    871 	py_decref(permlist);
    872 	py_decref(boollist);
    873 
    874 cleanup:
    875 	free(tmp);
    876 	free(rule_str);
    877 	free(expr);
    878 	errno = error;
    879 	return output;
    880 }
    881 
    882 PyObject* search(bool allow,
    883 		 bool neverallow,
    884 		 bool auditallow,
    885 		 bool dontaudit,
    886 		 bool transition,
    887 		 bool role_allow,
    888 		 const char *src_name,
    889 		 const char *tgt_name,
    890 		 const char *class_name,
    891 		 const char *permlist
    892 	)
    893 {
    894 	options_t cmd_opts;
    895 	PyObject *output = NULL;
    896 	apol_vector_t *v = NULL;
    897 
    898 	memset(&cmd_opts, 0, sizeof(cmd_opts));
    899 	cmd_opts.indirect = true;
    900 	cmd_opts.show_cond = true;
    901 	cmd_opts.allow = allow;
    902 	cmd_opts.nallow = neverallow;
    903 	cmd_opts.auditallow = auditallow;
    904 	cmd_opts.dontaudit = dontaudit;
    905 	cmd_opts.type = transition;
    906 	cmd_opts.role_allow = role_allow;
    907 	if (src_name)
    908 		cmd_opts.src_name = strdup(src_name);
    909 	if (tgt_name)
    910 		cmd_opts.tgt_name = strdup(tgt_name);
    911 	if (class_name)
    912 		cmd_opts.class_name = strdup(class_name);
    913 	if (permlist){
    914 		cmd_opts.perm_vector = apol_vector_create(free);
    915 		cmd_opts.permlist = strdup(permlist);
    916 	}
    917 	if (!cmd_opts.semantic && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) {
    918 		if (qpol_policy_build_syn_rule_table(apol_policy_get_qpol(policy))) {
    919 			PyErr_SetString(PyExc_RuntimeError,"Query failed");
    920 			goto cleanup;
    921 		}
    922 	}
    923 
    924 	/* if syntactic rules are not available always do semantic search */
    925 	if (!qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) {
    926 		cmd_opts.semantic = 1;
    927 	}
    928 
    929 	/* supress line numbers if doing semantic search or not available */
    930 	if (cmd_opts.semantic || !qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_LINE_NUMBERS)) {
    931 		cmd_opts.lineno = 0;
    932 	}
    933 	if (perform_av_query(policy, &cmd_opts, &v)) {
    934 		goto cleanup;
    935 	}
    936 	output = PyList_New(0);
    937 	if (!output)
    938 		goto cleanup;
    939 
    940 	if (v) {
    941 		get_av_results(policy, v, output);
    942 	}
    943 
    944 	apol_vector_destroy(&v);
    945 	if (perform_te_query(policy, &cmd_opts, &v)) {
    946 		goto cleanup;
    947 	}
    948 	if (v) {
    949 		get_te_results(policy, v, output);
    950 	}
    951 
    952 	if (cmd_opts.all || cmd_opts.type) {
    953 		apol_vector_destroy(&v);
    954 		if (perform_ft_query(policy, &cmd_opts, &v)) {
    955 			goto cleanup;
    956 		}
    957 
    958 		if (v) {
    959 			get_ft_results(policy, v, output);
    960 		}
    961 	}
    962 
    963 	if (cmd_opts.all || cmd_opts.role_allow) {
    964 		apol_vector_destroy(&v);
    965 		if (perform_ra_query(policy, &cmd_opts, &v)) {
    966 			goto cleanup;
    967 		}
    968 
    969 		if (v) {
    970 			get_ra_results(policy, v, output);
    971 		}
    972 	}
    973 
    974 	apol_vector_destroy(&v);
    975 
    976       cleanup:
    977 	free(cmd_opts.src_name);
    978 	free(cmd_opts.tgt_name);
    979 	free(cmd_opts.class_name);
    980 	free(cmd_opts.permlist);
    981 	free(cmd_opts.bool_name);
    982 	free(cmd_opts.src_role_name);
    983 	free(cmd_opts.tgt_role_name);
    984 	apol_vector_destroy(&cmd_opts.perm_vector);
    985 	apol_vector_destroy(&cmd_opts.class_vector);
    986 
    987 	if (output && PyList_GET_SIZE(output) == 0) {
    988 		py_decref(output);
    989 		return Py_None;
    990 	}
    991 	return output;
    992 }
    993 
    994 static int Dict_ContainsInt(PyObject *dict, const char *key){
    995     PyObject *item = PyDict_GetItemString(dict, key);
    996     if (item)
    997 	return PyInt_AsLong(item);
    998     return false;
    999 }
   1000 
   1001 static const char *Dict_ContainsString(PyObject *dict, const char *key){
   1002     PyObject *item = PyDict_GetItemString(dict, key);
   1003     if (item)
   1004 	return PyString_AsString(item);
   1005     return NULL;
   1006 }
   1007 
   1008 PyObject *wrap_search(PyObject *UNUSED(self), PyObject *args){
   1009     PyObject *dict;
   1010     if (!PyArg_ParseTuple(args, "O", &dict))
   1011 	return NULL;
   1012     int allow = Dict_ContainsInt(dict, "allow");
   1013     int neverallow = Dict_ContainsInt(dict, "neverallow");
   1014     int auditallow = Dict_ContainsInt(dict, "auditallow");
   1015     int dontaudit = Dict_ContainsInt(dict, "dontaudit");
   1016     int transition = Dict_ContainsInt(dict, "transition");
   1017     int role_allow = Dict_ContainsInt(dict, "role_allow");
   1018 
   1019     if (!policy) {
   1020 	    PyErr_SetString(PyExc_RuntimeError,"Policy not loaded");
   1021 	    return NULL;
   1022     }
   1023     const char *src_name = Dict_ContainsString(dict, "source");
   1024     const char *tgt_name = Dict_ContainsString(dict, "target");
   1025     const char *class_name = Dict_ContainsString(dict, "class");
   1026     const char *permlist = Dict_ContainsString(dict, "permlist");
   1027 
   1028     return search(allow, neverallow, auditallow, dontaudit, transition, role_allow, src_name, tgt_name, class_name, permlist);
   1029 }
   1030