1 // Author: Thomas Liu <tliu@redhat.com>
2 
3 /**
4  *  @file
5  *  Python bindings used to search TE rules.
6  *
7  *  @author Thomas Liu  <tliu@redhat.com>
8  *  @author Dan Walsh  <dwalsh@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@tresys.com
13  *  @author Jeremy A. Mowery jmowery@tresys.com
14  *  @author Paul Rosenfeld  prosenfeld@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 
py_tuple_insert_obj(PyObject * tuple,int pos,PyObject * obj)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 
perform_ra_query(const apol_policy_t * policy,const options_t * opt,apol_vector_t ** v)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 
get_ra_results(const apol_policy_t * policy,const apol_vector_t * v,PyObject * output)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 
perform_te_query(const apol_policy_t * policy,const options_t * opt,apol_vector_t ** v)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 
get_bool(const qpol_policy_t * q,const qpol_cond_t * cond,int enabled)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 
get_te_results(const apol_policy_t * policy,const apol_vector_t * v,PyObject * output)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 
perform_ft_query(const apol_policy_t * policy,const options_t * opt,apol_vector_t ** v)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 
get_ft_results(const apol_policy_t * policy,const apol_vector_t * v,PyObject * list)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 
perform_av_query(const apol_policy_t * policy,const options_t * opt,apol_vector_t ** v)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 
get_av_results(const apol_policy_t * policy,const apol_vector_t * v,PyObject * output)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 
search(bool allow,bool neverallow,bool auditallow,bool dontaudit,bool transition,bool role_allow,const char * src_name,const char * tgt_name,const char * class_name,const char * permlist)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 
Dict_ContainsInt(PyObject * dict,const char * key)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 
Dict_ContainsString(PyObject * dict,const char * key)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 
wrap_search(PyObject * UNUSED (self),PyObject * args)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