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