1 /**
2 * @file
3 * Command line tool to search TE rules.
4 *
5 * @author Frank Mayer mayerf@tresys.com
6 * @author Jeremy A. Mowery jmowery@tresys.com
7 * @author Paul Rosenfeld prosenfeld@tresys.com
8 * @author Thomas Liu <tliu@redhat.com>
9 * @author Dan Walsh <dwalsh@redhat.com>
10 *
11 * Copyright (C) 2003-2008 Tresys Technology, LLC
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 */
27
28 /**
29 * This is a modified version of seinfo to be used as part of a library for
30 * Python bindings.
31 */
32
33 #include "common.h"
34 #include "policy.h"
35
36 /* libapol */
37 #include <apol/policy-query.h>
38 #include <apol/render.h>
39 #include <apol/util.h>
40 #include <apol/vector.h>
41
42 /* libqpol */
43 #include <qpol/policy.h>
44 #include <qpol/util.h>
45
46 /* other */
47 #include <errno.h>
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <assert.h>
52
53 #define COPYRIGHT_INFO "Copyright (C) 2003-2007 Tresys Technology, LLC"
54
55 enum input
56 {
57 TYPE, ATTRIBUTE, ROLE, USER, PORT, BOOLEAN, CLASS, SENS, CATS
58 };
59
py_insert_long(PyObject * dict,const char * name,int value)60 static int py_insert_long(PyObject *dict, const char *name, int value)
61 {
62 int rt;
63 PyObject *obj = PyLong_FromLong(value);
64 if (!obj) return -1;
65 rt = PyDict_SetItemString(dict, name, obj);
66 Py_DECREF(obj);
67 return rt;
68 }
69
py_insert_bool(PyObject * dict,const char * name,int value)70 static int py_insert_bool(PyObject *dict, const char *name, int value)
71 {
72 int rt;
73 PyObject *obj = PyBool_FromLong(value);
74 if (!obj) return -1;
75 rt = PyDict_SetItemString(dict, name, obj);
76 Py_DECREF(obj);
77 return rt;
78 }
79
80 /**
81 * Get a policy's MLS sensitivities.
82 * If this function is given a name, it will attempt to
83 * get statistics about a particular sensitivity; otherwise
84 * the function gets statistics about all of the policy's
85 * sensitivities.
86 *
87 * @param name Reference to a sensitivity's name; if NULL,
88 * all sensitivities will be considered
89 * @param policydb Reference to a policy
90 *
91 * @return 0 on success, < 0 on error.
92 */
get_sens(const char * name,const apol_policy_t * policydb)93 static PyObject* get_sens(const char *name, const apol_policy_t * policydb)
94 {
95 PyObject *dict = NULL;
96 int error = 0;
97 int rt = 0;
98 size_t i;
99 char *tmp = NULL;
100 const char *lvl_name = NULL;
101 apol_level_query_t *query = NULL;
102 apol_vector_t *v = NULL;
103 const qpol_level_t *level = NULL;
104 apol_mls_level_t *ap_mls_lvl = NULL;
105 qpol_policy_t *q = apol_policy_get_qpol(policydb);
106
107 query = apol_level_query_create();
108 if (!query)
109 goto cleanup;
110 if (apol_level_query_set_sens(policydb, query, name))
111 goto cleanup;
112 if (apol_level_get_by_query(policydb, query, &v))
113 goto cleanup;
114
115 dict = PyDict_New();
116 if (!dict) goto err;
117 for (i = 0; i < apol_vector_get_size(v); i++) {
118 level = apol_vector_get_element(v, i);
119 if (qpol_level_get_name(q, level, &lvl_name))
120 goto err;
121 ap_mls_lvl = (apol_mls_level_t *) apol_mls_level_create_from_qpol_level_datum(policydb, level);
122 tmp = apol_mls_level_render(policydb, ap_mls_lvl);
123 apol_mls_level_destroy(&ap_mls_lvl);
124 if (!tmp)
125 goto cleanup;
126 if (py_insert_string(dict, lvl_name, tmp))
127 goto err;
128 free(tmp); tmp = NULL;
129 if (rt) goto err;
130 }
131
132 if (name && !apol_vector_get_size(v)) {
133 goto cleanup;
134 }
135
136 goto cleanup;
137 err:
138 error = errno;
139 PyErr_SetString(PyExc_RuntimeError,strerror(error));
140 py_decref(dict); dict = NULL;
141 cleanup:
142 free(tmp);
143 apol_level_query_destroy(&query);
144 apol_vector_destroy(&v);
145 errno = error;
146 return dict;
147 }
148
149 /**
150 * Compare two qpol_cat_datum_t objects.
151 * This function is meant to be passed to apol_vector_compare
152 * as the callback for performing comparisons.
153 *
154 * @param datum1 Reference to a qpol_type_datum_t object
155 * @param datum2 Reference to a qpol_type_datum_t object
156 * @param data Reference to a policy
157 * @return Greater than 0 if the first argument is less than the second argument,
158 * less than 0 if the first argument is greater than the second argument,
159 * 0 if the arguments are equal
160 */
qpol_cat_datum_compare(const void * datum1,const void * datum2,void * data)161 static int qpol_cat_datum_compare(const void *datum1, const void *datum2, void *data)
162 {
163 const qpol_cat_t *cat_datum1 = NULL, *cat_datum2 = NULL;
164 apol_policy_t *policydb = NULL;
165 qpol_policy_t *q;
166 uint32_t val1, val2;
167
168 policydb = (apol_policy_t *) data;
169 q = apol_policy_get_qpol(policydb);
170 assert(policydb);
171
172 if (!datum1 || !datum2)
173 goto exit_err;
174 cat_datum1 = datum1;
175 cat_datum2 = datum2;
176
177 if (qpol_cat_get_value(q, cat_datum1, &val1))
178 goto exit_err;
179 if (qpol_cat_get_value(q, cat_datum2, &val2))
180 goto exit_err;
181
182 return (val1 > val2) ? 1 : ((val1 == val2) ? 0 : -1);
183
184 exit_err:
185 assert(0);
186 return 0;
187 }
188
189 /**
190 * Compare two qpol_level_datum_t objects.
191 * This function is meant to be passed to apol_vector_compare
192 * as the callback for performing comparisons.
193 *
194 * @param datum1 Reference to a qpol_level_datum_t object
195 * @param datum2 Reference to a qpol_level_datum_t object
196 * @param data Reference to a policy
197 * @return Greater than 0 if the first argument is less than the second argument,
198 * less than 0 if the first argument is greater than the second argument,
199 * 0 if the arguments are equal
200 */
qpol_level_datum_compare(const void * datum1,const void * datum2,void * data)201 static int qpol_level_datum_compare(const void *datum1, const void *datum2, void *data)
202 {
203 const qpol_level_t *lvl_datum1 = NULL, *lvl_datum2 = NULL;
204 apol_policy_t *policydb = NULL;
205 qpol_policy_t *q;
206 uint32_t val1, val2;
207
208 policydb = (apol_policy_t *) data;
209 assert(policydb);
210 q = apol_policy_get_qpol(policydb);
211
212 if (!datum1 || !datum2)
213 goto exit_err;
214 lvl_datum1 = datum1;
215 lvl_datum2 = datum2;
216
217 if (qpol_level_get_value(q, lvl_datum1, &val1))
218 goto exit_err;
219 if (qpol_level_get_value(q, lvl_datum2, &val2))
220 goto exit_err;
221
222 return (val1 > val2) ? 1 : ((val1 == val2) ? 0 : -1);
223
224 exit_err:
225 assert(0);
226 return 0;
227 }
228
229 /**
230 * Gets a textual representation of a MLS category and
231 * all of that category's sensitivies.
232 *
233 * @param type_datum Reference to sepol type_datum
234 * @param policydb Reference to a policy
235 */
get_cat_sens(const qpol_cat_t * cat_datum,const apol_policy_t * policydb)236 static PyObject* get_cat_sens(const qpol_cat_t * cat_datum, const apol_policy_t * policydb)
237 {
238 const char *cat_name, *lvl_name;
239 apol_level_query_t *query = NULL;
240 apol_vector_t *v = NULL;
241 const qpol_level_t *lvl_datum = NULL;
242 qpol_policy_t *q = apol_policy_get_qpol(policydb);
243 size_t i, n_sens = 0;
244 int error = 0;
245 PyObject *list = NULL;
246 PyObject *dict = PyDict_New();
247 if (!dict) goto err;
248 if (!cat_datum || !policydb)
249 goto err;
250
251 /* get category name for apol query */
252 if (qpol_cat_get_name(q, cat_datum, &cat_name))
253 goto cleanup;
254
255 query = apol_level_query_create();
256 if (!query)
257 goto err;
258 if (apol_level_query_set_cat(policydb, query, cat_name))
259 goto err;
260 if (apol_level_get_by_query(policydb, query, &v))
261 goto err;
262 apol_vector_sort(v, &qpol_level_datum_compare, (void *)policydb);
263 dict = PyDict_New();
264 if (!dict) goto err;
265 if (py_insert_string(dict, "name", cat_name))
266 goto err;
267 n_sens = apol_vector_get_size(v);
268 list = PyList_New(0);
269 if (!list) goto err;
270 for (i = 0; i < n_sens; i++) {
271 lvl_datum = (qpol_level_t *) apol_vector_get_element(v, i);
272 if (!lvl_datum)
273 goto err;
274 if (qpol_level_get_name(q, lvl_datum, &lvl_name))
275 goto err;
276 if (py_append_string(list, lvl_name))
277 goto err;
278 }
279 if (py_insert_obj(dict, "level", list))
280 goto err;
281 Py_DECREF(list);
282
283 goto cleanup;
284 err:
285 error = errno;
286 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
287 py_decref(list); list = NULL;
288 py_decref(dict); dict = NULL;
289 cleanup:
290 apol_level_query_destroy(&query);
291 apol_vector_destroy(&v);
292 errno = error;
293 return dict;
294 }
295
296 /**
297 * Prints statistics regarding a policy's MLS categories.
298 * If this function is given a name, it will attempt to
299 * get statistics about a particular category; otherwise
300 * the function gets statistics about all of the policy's
301 * categories.
302 *
303 * @param name Reference to a MLS category's name; if NULL,
304 * all categories will be considered
305 * @param policydb Reference to a policy
306 *
307 * @return 0 on success, < 0 on error.
308 */
get_cats(const char * name,const apol_policy_t * policydb)309 static PyObject* get_cats(const char *name, const apol_policy_t * policydb)
310 {
311 PyObject *obj = NULL;
312 apol_cat_query_t *query = NULL;
313 apol_vector_t *v = NULL;
314 const qpol_cat_t *cat_datum = NULL;
315 size_t i, n_cats;
316 int error = 0;
317 int rt;
318 PyObject *list = PyList_New(0);
319 if (!list) goto err;
320
321 query = apol_cat_query_create();
322 if (!query)
323 goto err;
324 if (apol_cat_query_set_cat(policydb, query, name))
325 goto err;
326 if (apol_cat_get_by_query(policydb, query, &v))
327 goto err;
328 n_cats = apol_vector_get_size(v);
329 apol_vector_sort(v, &qpol_cat_datum_compare, (void *)policydb);
330
331 for (i = 0; i < n_cats; i++) {
332 cat_datum = apol_vector_get_element(v, i);
333 if (!cat_datum)
334 goto err;
335 obj = get_cat_sens(cat_datum, policydb);
336 if (!obj)
337 goto err;
338 rt = py_append_obj(list, obj);
339 Py_DECREF(obj);
340 if (rt) goto err;
341 }
342
343 if (name && !n_cats) {
344 goto err;
345 }
346
347 goto cleanup;
348 err:
349 error = errno;
350 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
351 py_decref(list); list = NULL;
352 cleanup:
353 apol_cat_query_destroy(&query);
354 apol_vector_destroy(&v);
355 errno = error;
356 return list;
357 }
358
359 /**
360 * Get the alias of a type.
361 *
362 * @param type_datum Reference to sepol type_datum
363 * @param policydb Reference to a policy
364 * attributes
365 */
get_type_aliases(const qpol_type_t * type_datum,const apol_policy_t * policydb)366 static PyObject* get_type_aliases(const qpol_type_t * type_datum, const apol_policy_t * policydb)
367 {
368 qpol_iterator_t *iter = NULL;
369 size_t alias_size;
370 unsigned char isattr, isalias;
371 const char *type_name = NULL;
372 const char *alias_name;
373 int error = 0;
374 qpol_policy_t *q = apol_policy_get_qpol(policydb);
375 PyObject *list = PyList_New(0);
376 if (!list) goto err;
377
378 if (qpol_type_get_name(q, type_datum, &type_name))
379 goto cleanup;
380 if (qpol_type_get_isattr(q, type_datum, &isattr))
381 goto cleanup;
382 if (qpol_type_get_isalias(q, type_datum, &isalias))
383 goto cleanup;
384
385 if (qpol_type_get_alias_iter(q, type_datum, &iter))
386 goto cleanup;
387 if (qpol_iterator_get_size(iter, &alias_size))
388 goto cleanup;
389 if (alias_size > 0) {
390 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
391 if (qpol_iterator_get_item(iter, (void **)&alias_name))
392 goto err;
393 if (py_append_string(list, alias_name))
394 goto err;
395 }
396 }
397 goto cleanup;
398
399 err:
400 error = errno;
401 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
402 py_decref(list); list = NULL;
403
404 cleanup:
405 qpol_iterator_destroy(&iter);
406 errno = error;
407 return list;
408 }
409
410 /**
411 * Gets a textual representation of an attribute, and
412 * all of that attribute's types.
413 *
414 * @param type_datum Reference to sepol type_datum
415 * @param policydb Reference to a policy
416 */
get_attr(const qpol_type_t * type_datum,const apol_policy_t * policydb)417 static PyObject* get_attr(const qpol_type_t * type_datum, const apol_policy_t * policydb)
418 {
419 PyObject *list = NULL;
420 const qpol_type_t *attr_datum = NULL;
421 qpol_iterator_t *iter = NULL;
422 const char *attr_name = NULL, *type_name = NULL;
423 qpol_policy_t *q = apol_policy_get_qpol(policydb);
424 unsigned char isattr;
425 int error = 0;
426 int rt = 0;
427 PyObject *dict = PyDict_New();
428 if (!dict) goto err;
429
430 if (qpol_type_get_name(q, type_datum, &attr_name))
431 goto err;
432
433 if (py_insert_string(dict, "name", attr_name))
434 goto err;
435
436 /* get an iterator over all types this attribute has */
437 if (qpol_type_get_isattr(q, type_datum, &isattr))
438 goto err;
439
440 if (isattr) { /* sanity check */
441 if (qpol_type_get_type_iter(q, type_datum, &iter))
442 goto err;
443 list = PyList_New(0);
444 if (!list) goto err;
445
446 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
447 if (qpol_iterator_get_item(iter, (void **)&attr_datum))
448 goto err;
449 if (qpol_type_get_name(q, attr_datum, &type_name))
450 goto err;
451 if (py_append_string(list, type_name))
452 goto err;
453 }
454 qpol_iterator_destroy(&iter);
455 rt = PyDict_SetItemString(dict, "types", list);
456 Py_DECREF(list); list = NULL;
457 if (rt) goto err;
458 } else /* this should never happen */
459 goto err;
460 goto cleanup;
461
462 err:
463 error = errno;
464 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
465 py_decref(dict); dict = NULL;
466 py_decref(list);
467
468 cleanup:
469 qpol_iterator_destroy(&iter);
470 errno = error;
471 return dict;
472 }
473
474 /**
475 * Gets statistics regarding a policy's attributes.
476 * If this function is given a name, it will attempt to
477 * get statistics about a particular attribute; otherwise
478 * the function gets statistics about all of the policy's
479 * attributes.
480 *
481 * @param name Reference to an attribute's name; if NULL,
482 * all object classes will be considered
483 * @param policydb Reference to a policy
484 *
485 * @return 0 on success, < 0 on error.
486 */
get_attribs(const char * name,const apol_policy_t * policydb)487 static PyObject* get_attribs(const char *name, const apol_policy_t * policydb)
488 {
489 PyObject *obj;
490 apol_attr_query_t *attr_query = NULL;
491 apol_vector_t *v = NULL;
492 const qpol_type_t *type_datum = NULL;
493 size_t n_attrs, i;
494 int error = 0;
495 int rt = 0;
496 PyObject *list = PyList_New(0);
497 if (!list) goto err;
498
499 /* we are only getting information about 1 attribute */
500 if (name != NULL) {
501 attr_query = apol_attr_query_create();
502 if (!attr_query)
503 goto err;
504 if (apol_attr_query_set_attr(policydb, attr_query, name))
505 goto err;
506 if (apol_attr_get_by_query(policydb, attr_query, &v))
507 goto err;
508 apol_attr_query_destroy(&attr_query);
509 if (apol_vector_get_size(v) == 0) {
510 apol_vector_destroy(&v);
511 errno = EINVAL;
512 goto err;
513 }
514
515 type_datum = apol_vector_get_element(v, (size_t) 0);
516 obj = get_attr(type_datum, policydb);
517 rt = py_append_obj(list, obj);
518 Py_DECREF(obj);
519 if (rt) goto err;
520 } else {
521 attr_query = apol_attr_query_create();
522 if (!attr_query)
523 goto err;
524 if (apol_attr_get_by_query(policydb, attr_query, &v))
525 goto err;
526 apol_attr_query_destroy(&attr_query);
527 n_attrs = apol_vector_get_size(v);
528
529 for (i = 0; i < n_attrs; i++) {
530 /* get qpol_type_t* item from vector */
531 type_datum = (qpol_type_t *) apol_vector_get_element(v, (size_t) i);
532 if (!type_datum)
533 goto err;
534 obj = get_attr(type_datum, policydb);
535 rt = py_append_obj(list, obj);
536 Py_DECREF(obj);
537 if (rt) goto err;
538 }
539 }
540 apol_vector_destroy(&v);
541 goto cleanup;
542
543 err:
544 error = errno;
545 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
546 py_decref(list); list = NULL;
547
548 cleanup:
549 apol_attr_query_destroy(&attr_query);
550 apol_vector_destroy(&v);
551 errno = error;
552 return list;
553 }
554
555 /**
556 * Get a textual representation of a type, and
557 * all of that type's attributes.
558 *
559 * @param type_datum Reference to sepol type_datum
560 * @param policydb Reference to a policy
561 */
get_type_attrs(const qpol_type_t * type_datum,const apol_policy_t * policydb)562 static PyObject* get_type_attrs(const qpol_type_t * type_datum, const apol_policy_t * policydb)
563 {
564 qpol_iterator_t *iter = NULL;
565 const char *attr_name = NULL;
566 const qpol_type_t *attr_datum = NULL;
567 qpol_policy_t *q = apol_policy_get_qpol(policydb);
568 int error = 0;
569 PyObject *list = PyList_New(0);
570 if (!list) goto err;
571
572 if (qpol_type_get_attr_iter(q, type_datum, &iter))
573 goto err;
574
575 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
576 if (qpol_iterator_get_item(iter, (void **)&attr_datum))
577 goto err;
578 if (qpol_type_get_name(q, attr_datum, &attr_name))
579 goto err;
580 if (py_append_string(list, attr_name))
581 goto err;
582 }
583 goto cleanup;
584
585 err:
586 error = errno;
587 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
588 py_decref(list); list = NULL;
589
590 cleanup:
591 qpol_iterator_destroy(&iter);
592 errno = error;
593 return list;
594 }
595
get_type(const qpol_type_t * type_datum,const apol_policy_t * policydb)596 static PyObject* get_type(const qpol_type_t * type_datum, const apol_policy_t * policydb) {
597
598 PyObject *obj;
599 qpol_policy_t *q = apol_policy_get_qpol(policydb);
600 const char *type_name = NULL;
601 int error = 0;
602 int rt;
603 unsigned char isalias, ispermissive, isattr;
604 PyObject *dict = PyDict_New();
605 if (!dict) goto err;
606
607 if (qpol_type_get_name(q, type_datum, &type_name))
608 goto err;
609 if (qpol_type_get_isalias(q, type_datum, &isalias))
610 goto err;
611 if (qpol_type_get_isattr(q, type_datum, &isattr))
612 goto err;
613 if (qpol_type_get_ispermissive(q, type_datum, &ispermissive))
614 goto err;
615
616 if (py_insert_string(dict, "name", type_name))
617 goto err;
618
619 if (py_insert_bool(dict, "permissive", ispermissive))
620 goto err;
621
622 if (!isattr && !isalias) {
623 obj = get_type_attrs(type_datum, policydb);
624 rt = py_insert_obj(dict, "attributes", obj);
625 Py_DECREF(obj);
626 if (rt) goto err;
627 }
628
629 obj = get_type_aliases(type_datum, policydb);
630 rt = py_insert_obj(dict, "aliases", obj);
631 Py_DECREF(obj);
632 if (rt) goto err;
633 goto cleanup;
634
635 err:
636 error = errno;
637 PyErr_SetString(PyExc_RuntimeError,strerror(error));
638 py_decref(dict); dict = NULL;
639
640 cleanup:
641 errno = error;
642 return dict;
643 }
644
645 /**
646 * Gets statistics regarding a policy's booleans.
647 * If this function is given a name, it will attempt to
648 * get statistics about a particular boolean; otherwise
649 * the function gets statistics about all of the policy's booleans.
650 *
651 * @param name Reference to a boolean's name; if NULL,
652 * all booleans will be considered
653 * @param policydb Reference to a policy
654 *
655 * @return new reference, or NULL (setting an exception)
656 */
get_booleans(const char * name,const apol_policy_t * policydb)657 static PyObject* get_booleans(const char *name, const apol_policy_t * policydb)
658 {
659 PyObject *dict = NULL;
660 int error = 0;
661 int rt = 0;
662 const char *bool_name = NULL;
663 int state;
664 qpol_bool_t *bool_datum = NULL;
665 qpol_iterator_t *iter = NULL;
666 qpol_policy_t *q = apol_policy_get_qpol(policydb);
667 size_t n_bools = 0;
668 PyObject *list = PyList_New(0);
669 if (!list) goto err;
670
671 if (name != NULL) {
672 if (qpol_policy_get_bool_by_name(q, name, &bool_datum))
673 goto err;
674 if (qpol_bool_get_state(q, bool_datum, &state))
675 goto err;
676
677 dict = PyDict_New();
678 if (!dict) goto err;
679 if (py_insert_string(dict, "name", name))
680 goto err;
681 if (py_insert_bool(dict, "name", state))
682 goto err;
683 rt = py_append_obj(list, dict);
684 Py_DECREF(dict); dict = NULL;
685 if (rt) goto err;
686 } else {
687 if (qpol_policy_get_bool_iter(q, &iter))
688 goto err;
689 if (qpol_iterator_get_size(iter, &n_bools))
690 goto err;
691 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
692 if (qpol_iterator_get_item(iter, (void **)&bool_datum))
693 goto err;
694 if (qpol_bool_get_name(q, bool_datum, &bool_name))
695 goto err;
696 if (qpol_bool_get_state(q, bool_datum, &state))
697 goto err;
698
699 dict = PyDict_New();
700 if (!dict) goto err;
701 if (py_insert_string(dict, "name", bool_name))
702 goto err;
703 if (py_insert_bool(dict, "state", state))
704 goto err;
705 rt = py_append_obj(list, dict);
706 Py_DECREF(dict); dict = NULL;
707 if (rt) goto err;
708 }
709 qpol_iterator_destroy(&iter);
710 }
711 goto cleanup;
712
713 err:
714 error = errno;
715 PyErr_SetString(PyExc_RuntimeError,strerror(error));
716 py_decref(list); list = NULL;
717 py_decref(dict); dict = NULL;
718
719 cleanup:
720 qpol_iterator_destroy(&iter);
721 errno = error;
722 return list;
723 }
724
725 /**
726 * Gets a textual representation of a user, and
727 * all of that user's roles.
728 *
729 * @param type_datum Reference to sepol type_datum
730 * @param policydb Reference to a policy
731 * roles
732 */
get_user(const qpol_user_t * user_datum,const apol_policy_t * policydb)733 static PyObject* get_user(const qpol_user_t * user_datum, const apol_policy_t * policydb)
734 {
735 int error = 0;
736 int rt;
737 const qpol_role_t *role_datum = NULL;
738 qpol_iterator_t *iter = NULL;
739 const qpol_mls_range_t *range = NULL;
740 const qpol_mls_level_t *dflt_level = NULL;
741 apol_mls_level_t *ap_lvl = NULL;
742 apol_mls_range_t *ap_range = NULL;
743 qpol_policy_t *q = apol_policy_get_qpol(policydb);
744 char *tmp = NULL;
745 const char *user_name, *role_name;
746 PyObject *dict = NULL;
747 PyObject *list = PyList_New(0);
748 if (!list) goto err;
749
750 if (qpol_user_get_name(q, user_datum, &user_name))
751 goto err;
752
753 dict = PyDict_New();
754 if (!dict) goto err;
755
756 if (py_insert_string(dict, "name", user_name))
757 goto err;
758
759 if (qpol_policy_has_capability(q, QPOL_CAP_MLS)) {
760 if (qpol_user_get_dfltlevel(q, user_datum, &dflt_level))
761 goto err;
762 ap_lvl = apol_mls_level_create_from_qpol_mls_level(policydb, dflt_level);
763 tmp = apol_mls_level_render(policydb, ap_lvl);
764 if (!tmp) goto err;
765 if (py_insert_string(dict, "level", tmp))
766 goto err;
767 free(tmp); tmp = NULL;
768
769 if (qpol_user_get_range(q, user_datum, &range))
770 goto err;
771 ap_range = apol_mls_range_create_from_qpol_mls_range(policydb, range);
772 tmp = apol_mls_range_render(policydb, ap_range);
773 if (!tmp) goto err;
774 if (py_insert_string(dict, "range", tmp))
775 goto err;
776 free(tmp); tmp=NULL;
777 }
778
779 if (qpol_user_get_role_iter(q, user_datum, &iter))
780 goto err;
781 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
782 if (qpol_iterator_get_item(iter, (void **)&role_datum))
783 goto err;
784 if (qpol_role_get_name(q, role_datum, &role_name))
785 goto err;
786 if (py_append_string(list, role_name))
787 goto err;
788 }
789
790 rt = py_insert_obj(dict, "roles", list);
791 Py_DECREF(list); list=NULL;
792 if (rt) goto err;
793 goto cleanup;
794
795 err:
796 error = errno;
797 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
798 py_decref(list); list=NULL;
799 py_decref(dict); dict=NULL;
800
801 cleanup:
802 free(tmp);
803 qpol_iterator_destroy(&iter);
804 apol_mls_level_destroy(&ap_lvl);
805 apol_mls_range_destroy(&ap_range);
806 errno = error;
807 return dict;
808 }
809
810 /**
811 * Prints a textual representation of an object class and possibly
812 * all of that object class' permissions.
813 *
814 * @param type_datum Reference to sepol type_datum
815 * @param policydb Reference to a policy
816 */
get_class(const qpol_class_t * class_datum,const apol_policy_t * policydb)817 static PyObject* get_class(const qpol_class_t * class_datum, const apol_policy_t * policydb)
818 {
819 const char *class_name = NULL, *perm_name = NULL;
820 qpol_iterator_t *iter = NULL;
821 const qpol_common_t *common_datum = NULL;
822 qpol_policy_t *q = apol_policy_get_qpol(policydb);
823 int error = 0;
824 int rt;
825 PyObject *list = NULL;
826 PyObject *dict = PyDict_New();
827 if (!dict) goto err;
828
829 if (!class_datum)
830 goto err;
831
832 if (qpol_class_get_name(q, class_datum, &class_name))
833 goto err;
834
835 if (py_insert_string(dict, "name", class_name))
836 goto err;
837 /* get commons for this class */
838 if (qpol_class_get_common(q, class_datum, &common_datum))
839 goto err;
840
841 list = PyList_New(0);
842 if (!list) goto err;
843
844 if (common_datum) {
845 if (qpol_common_get_perm_iter(q, common_datum, &iter))
846 goto err;
847 /* print perms for the common */
848 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
849 if (qpol_iterator_get_item(iter, (void **)&perm_name))
850 goto err;
851 if (py_append_string(list, perm_name))
852 goto err;
853 }
854 }
855 /* print unique perms for this class */
856 if (qpol_class_get_perm_iter(q, class_datum, &iter))
857 goto err;
858 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
859 if (qpol_iterator_get_item(iter, (void **)&perm_name))
860 goto err;
861 if (py_append_string(list, perm_name))
862 goto err;
863 }
864 rt = py_insert_obj(dict, "permlist", list);
865 Py_DECREF(list); list = NULL;
866 if (rt) goto err;
867 qpol_iterator_destroy(&iter);
868 goto cleanup;
869
870 err:
871 error = errno;
872 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
873 py_decref(list); list=NULL;
874 py_decref(dict); dict=NULL;
875
876 cleanup:
877 errno = error;
878 qpol_iterator_destroy(&iter);
879 return dict;
880 }
881
882 /**
883 * Get statistics regarding a policy's object classes.
884 * If this function is given a name, it will attempt to
885 * print statistics about a particular object class; otherwise
886 * the function prints statistics about all of the policy's object
887 * classes.
888 *
889 * @param name Reference to an object class' name; if NULL,
890 * all object classes will be considered
891 * @param policydb Reference to a policy
892 *
893 * @return 0 on success, < 0 on error.
894 */
get_classes(const char * name,const apol_policy_t * policydb)895 static PyObject* get_classes(const char *name, const apol_policy_t * policydb)
896 {
897 qpol_iterator_t *iter = NULL;
898 size_t n_classes = 0;
899 const qpol_class_t *class_datum = NULL;
900 qpol_policy_t *q = apol_policy_get_qpol(policydb);
901 int error = 0;
902 int rt;
903 PyObject *obj;
904 PyObject *list = PyList_New(0);
905 if (!list) goto err;
906
907 if (name != NULL) {
908 if (qpol_policy_get_class_by_name(q, name, &class_datum))
909 goto err;
910 obj = get_class(class_datum, policydb);
911 rt = py_append_obj(list, obj);
912 Py_DECREF(obj);
913 if (rt) goto err;
914 } else {
915 if (qpol_policy_get_class_iter(q, &iter))
916 goto err;
917 if (qpol_iterator_get_size(iter, &n_classes))
918 goto err;
919
920 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
921 if (qpol_iterator_get_item(iter, (void **)&class_datum))
922 goto err;
923 obj = get_class(class_datum, policydb);
924 rt = py_append_obj(list, obj);
925 Py_DECREF(obj);
926 if (rt) goto err;
927 }
928 qpol_iterator_destroy(&iter);
929 }
930 goto cleanup;
931 err:
932 error = errno;
933 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
934 py_decref(list); list = NULL;
935
936 cleanup:
937 qpol_iterator_destroy(&iter);
938 errno = error;
939 return list;
940 }
941
942 /**
943 * Gets statistics regarding a policy's users.
944 * If this function is given a name, it will attempt to
945 * get statistics about a particular user; otherwise
946 * the function gets statistics about all of the policy's
947 * users.
948 *
949 * @param name Reference to a user's name; if NULL,
950 * all users will be considered
951 * @param policydb Reference to a policy
952 *
953 * @return 0 on success, < 0 on error.
954 */
get_users(const char * name,const apol_policy_t * policydb)955 static PyObject* get_users(const char *name, const apol_policy_t * policydb)
956 {
957 qpol_iterator_t *iter = NULL;
958 const qpol_user_t *user_datum = NULL;
959 qpol_policy_t *q = apol_policy_get_qpol(policydb);
960 int error = 0;
961 int rt;
962 PyObject *obj;
963 PyObject *list = PyList_New(0);
964 if (!list) goto err;
965
966 if (name != NULL) {
967 if (qpol_policy_get_user_by_name(q, name, &user_datum)) {
968 errno = EINVAL;
969 goto err;
970 }
971 obj = get_user(user_datum, policydb);
972 rt = py_append_obj(list, obj);
973 Py_DECREF(obj);
974 if (rt) goto err;
975 } else {
976 if (qpol_policy_get_user_iter(q, &iter))
977 goto err;
978
979 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
980 if (qpol_iterator_get_item(iter, (void **)&user_datum))
981 goto err;
982 obj = get_user(user_datum, policydb);
983 rt = py_append_obj(list, obj);
984 Py_DECREF(obj);
985 if (rt) goto err;
986 }
987 qpol_iterator_destroy(&iter);
988 }
989 goto cleanup;
990
991 err:
992 error = errno;
993 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
994 py_decref(list); list = NULL;
995
996 cleanup:
997 qpol_iterator_destroy(&iter);
998 errno = error;
999 return list;
1000 }
1001
1002 /**
1003 * get a textual representation of a role, and
1004 * all of that role's types.
1005 *
1006 * @param type_datum Reference to sepol type_datum
1007 * @param policydb Reference to a policy
1008 * types
1009 */
get_role(const qpol_role_t * role_datum,const apol_policy_t * policydb)1010 static PyObject* get_role(const qpol_role_t * role_datum, const apol_policy_t * policydb)
1011 {
1012 const char *role_name = NULL, *type_name = NULL;
1013 const qpol_role_t *dom_datum = NULL;
1014 const qpol_type_t *type_datum = NULL;
1015 qpol_iterator_t *iter = NULL;
1016 qpol_policy_t *q = apol_policy_get_qpol(policydb);
1017 size_t n_dom = 0, n_types = 0;
1018 int error = 0;
1019 int rt;
1020 PyObject *list = NULL;
1021 PyObject *dict = PyDict_New();
1022 if (!dict) goto err;
1023
1024 if (qpol_role_get_name(q, role_datum, &role_name))
1025 goto err;
1026 if (py_insert_string(dict, "name", role_name))
1027 goto err;
1028
1029 if (qpol_role_get_dominate_iter(q, role_datum, &iter))
1030 goto err;
1031 if (qpol_iterator_get_size(iter, &n_dom))
1032 goto err;
1033 if ((int)n_dom > 0) {
1034 list = PyList_New(0);
1035 if (!list) goto err;
1036 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
1037 if (qpol_iterator_get_item(iter, (void **)&dom_datum))
1038 goto err;
1039 if (qpol_role_get_name(q, dom_datum, &role_name))
1040 goto err;
1041 if (py_append_string(list, role_name))
1042 goto err;
1043 }
1044 rt = py_insert_obj(dict, "roles", list);
1045 Py_DECREF(list); list = NULL;
1046 if (rt) goto err;
1047 }
1048 qpol_iterator_destroy(&iter);
1049
1050 if (qpol_role_get_type_iter(q, role_datum, &iter))
1051 goto err;
1052 if (qpol_iterator_get_size(iter, &n_types))
1053 goto err;
1054 if ((int)n_types > 0) {
1055 list = PyList_New(0);
1056 if (!list) goto err;
1057 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
1058 if (qpol_iterator_get_item(iter, (void **)&type_datum))
1059 goto err;
1060 if (qpol_type_get_name(q, type_datum, &type_name))
1061 goto err;
1062 if (py_append_string(list, type_name))
1063 goto err;
1064 }
1065 rt = py_insert_obj(dict, "types", list);
1066 Py_DECREF(list); list = NULL;
1067 if (rt) goto err;
1068 }
1069 goto cleanup;
1070
1071 err:
1072 error = errno;
1073 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
1074 py_decref(list); list = NULL;
1075 py_decref(dict); dict = NULL;
1076
1077 cleanup:
1078 qpol_iterator_destroy(&iter);
1079 errno = error;
1080 return dict;
1081 }
1082
1083 /**
1084 * Get statistics regarding a policy's ports.
1085 * If this function is given a name, it will attempt to
1086 * get statistics about a particular port; otherwise
1087 * the function get statistics about all of the policy's ports.
1088 *
1089 * @param name Reference to an port's name; if NULL,
1090 * all ports will be considered
1091 * @param policydb Reference to a policy
1092 *
1093 * @return 0 on success, < 0 on error.
1094 */
get_ports(const char * num,const apol_policy_t * policydb)1095 static PyObject* get_ports(const char *num, const apol_policy_t * policydb)
1096 {
1097 const qpol_portcon_t *portcon = NULL;
1098 qpol_iterator_t *iter = NULL;
1099 uint16_t low_port, high_port;
1100 uint8_t ocon_proto;
1101 qpol_policy_t *q = apol_policy_get_qpol(policydb);
1102 const qpol_context_t *ctxt = NULL;
1103 const char *proto_str = NULL;
1104 const char *type = NULL;
1105 const apol_mls_range_t *range = NULL;
1106 char *range_str = NULL;
1107 apol_context_t *c = NULL;
1108 int error = 0;
1109 int rt = 0;
1110 PyObject *dict = NULL;
1111 PyObject *list = PyList_New(0);
1112 if (!list) goto err;
1113
1114 if (qpol_policy_get_portcon_iter(q, &iter))
1115 goto err;
1116
1117 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
1118 if (qpol_iterator_get_item(iter, (void **)&portcon))
1119 goto err;
1120 if (qpol_portcon_get_low_port(q, portcon, &low_port))
1121 goto err;
1122 if (qpol_portcon_get_high_port(q, portcon, &high_port))
1123 goto err;
1124 if (qpol_portcon_get_protocol(q, portcon, &ocon_proto))
1125 goto err;
1126 if (num) {
1127 if (atoi(num) < low_port || atoi(num) > high_port)
1128 continue;
1129 }
1130
1131 if ((ocon_proto != IPPROTO_TCP) &&
1132 (ocon_proto != IPPROTO_UDP))
1133 goto err;
1134
1135 if (qpol_portcon_get_context(q, portcon, &ctxt)) {
1136 PyErr_SetString(PyExc_RuntimeError, "Could not get for port context.");
1137 goto err;
1138 }
1139
1140 if ((proto_str = apol_protocol_to_str(ocon_proto)) == NULL) {
1141 PyErr_SetString(PyExc_RuntimeError, "Invalid protocol for port");
1142 goto err;
1143 }
1144
1145 if ((c = apol_context_create_from_qpol_context(policydb, ctxt)) == NULL) {
1146 goto err;
1147 }
1148
1149 if((type = apol_context_get_type(c)) == NULL) {
1150 apol_context_destroy(&c);
1151 goto err;
1152 }
1153
1154 dict = PyDict_New();
1155 if (!dict) goto err;
1156 if (py_insert_string(dict, "type", type))
1157 goto err;
1158
1159 if((range = apol_context_get_range(c)) != NULL) {
1160 range_str = apol_mls_range_render(policydb, range);
1161 if (range_str == NULL) {
1162 goto err;
1163 }
1164 if (py_insert_string(dict, "range", range_str))
1165 goto err;
1166 }
1167
1168 if (py_insert_string(dict, "protocol", proto_str))
1169 goto err;
1170
1171 if (py_insert_long(dict, "high", high_port))
1172 goto err;
1173
1174 if (py_insert_long(dict, "low", low_port))
1175 goto err;
1176
1177 rt = py_append_obj(list, dict);
1178 Py_DECREF(dict); dict = NULL;
1179 if (rt) goto err;
1180 }
1181 goto cleanup;
1182
1183 err:
1184 error = errno;
1185 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
1186 py_decref(list); list = NULL;
1187 py_decref(dict); dict = NULL;
1188
1189 cleanup:
1190 free(range_str);
1191 apol_context_destroy(&c);
1192 qpol_iterator_destroy(&iter);
1193 errno = error;
1194 return list;
1195 }
1196
1197 /**
1198 * Get statistics regarding a policy's roles.
1199 * If this function is given a name, it will attempt to
1200 * get statistics about a particular role; otherwise
1201 * the function get statistics about all of the policy's roles.
1202 *
1203 * @param name Reference to an role's name; if NULL,
1204 * all roles will be considered
1205 * @param policydb Reference to a policy
1206 *
1207 * @return 0 on success, < 0 on error.
1208 */
get_roles(const char * name,const apol_policy_t * policydb)1209 static PyObject* get_roles(const char *name, const apol_policy_t * policydb)
1210 {
1211 const qpol_role_t *role_datum = NULL;
1212 qpol_iterator_t *iter = NULL;
1213 qpol_policy_t *q = apol_policy_get_qpol(policydb);
1214 int error = 0;
1215 int rt;
1216 PyObject *obj;
1217 PyObject *list = PyList_New(0);
1218 if (!list) goto err;
1219
1220 if (name != NULL) {
1221 if (qpol_policy_get_role_by_name(q, name, &role_datum)) {
1222 errno = EINVAL;
1223 goto err;
1224 }
1225 obj = get_role(role_datum, policydb);
1226 rt = py_append_obj(list, obj);
1227 Py_DECREF(obj);
1228 if (rt) goto err;
1229 } else {
1230 if (qpol_policy_get_role_iter(q, &iter))
1231 goto err;
1232
1233 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
1234 if (qpol_iterator_get_item(iter, (void **)&role_datum))
1235 goto err;
1236 obj = get_role(role_datum, policydb);
1237 rt = py_append_obj(list, obj);
1238 Py_DECREF(obj);
1239 if (rt) goto err;
1240 }
1241 qpol_iterator_destroy(&iter);
1242 }
1243 goto cleanup;
1244
1245 err:
1246 error = errno;
1247 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
1248 py_decref(list); list = NULL;
1249
1250 cleanup:
1251 qpol_iterator_destroy(&iter);
1252 errno = error;
1253 return list;
1254 }
1255
1256 /**
1257 * Get statistics regarding a policy's types.
1258 * If this function is given a name, it will attempt to
1259 * print statistics about a particular type; otherwise
1260 * the function prints statistics about all of the policy's types.
1261 *
1262 * @param name Reference to a type's name; if NULL,
1263 * all object classes will be considered
1264 * @param policydb Reference to a policy
1265 *
1266 * @return 0 on success, < 0 on error.
1267 */
get_types(const char * name,const apol_policy_t * policydb)1268 static PyObject* get_types(const char *name, const apol_policy_t * policydb)
1269 {
1270 const qpol_type_t *type_datum = NULL;
1271 qpol_iterator_t *iter = NULL;
1272 qpol_policy_t *q = apol_policy_get_qpol(policydb);
1273 int error = 0;
1274 int rt;
1275 PyObject *obj;
1276 PyObject *list = PyList_New(0);
1277 if (!list) goto err;
1278 /* if name was provided, only print that name */
1279 if (name != NULL) {
1280 if (qpol_policy_get_type_by_name(q, name, &type_datum)) {
1281 errno = EINVAL;
1282 goto err;
1283 }
1284 obj = get_type(type_datum, policydb);
1285 rt = py_append_obj(list, obj);
1286 Py_DECREF(obj);
1287 if (rt) goto err;
1288 } else {
1289 if (qpol_policy_get_type_iter(q, &iter))
1290 goto err;
1291
1292 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
1293 if (qpol_iterator_get_item(iter, (void **)&type_datum))
1294 goto err;
1295 obj = get_type(type_datum, policydb);
1296 rt = py_append_obj(list, obj);
1297 Py_DECREF(obj);
1298 if (rt) goto err;
1299 }
1300 }
1301 goto cleanup;
1302
1303 err:
1304 error = errno;
1305 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
1306 py_decref(list); list = NULL;
1307
1308 cleanup:
1309 qpol_iterator_destroy(&iter);
1310 errno = error;
1311 return list;
1312 }
1313
info(int type,const char * name)1314 PyObject* info( int type, const char *name)
1315 {
1316 PyObject* output = NULL;
1317
1318 switch(type) {
1319 /* display requested info */
1320 case TYPE:
1321 output = get_types(name, policy);
1322 break;
1323 case ATTRIBUTE:
1324 output = get_attribs(name, policy);
1325 break;
1326 case ROLE:
1327 output = get_roles(name, policy);
1328 break;
1329 case USER:
1330 output = get_users(name, policy);
1331 break;
1332 case CLASS:
1333 output = get_classes(name, policy);
1334 break;
1335 case BOOLEAN:
1336 output = get_booleans(name, policy);
1337 break;
1338 case PORT:
1339 output = get_ports(name, policy);
1340 break;
1341 case SENS:
1342 output = get_sens(name, policy);
1343 break;
1344 case CATS:
1345 output = get_cats(name, policy);
1346 break;
1347 default:
1348 errno = EINVAL;
1349 PyErr_SetString(PyExc_RuntimeError,strerror(errno));
1350 break;
1351 }
1352
1353 return output;
1354 }
1355
wrap_info(PyObject * UNUSED (self),PyObject * args)1356 PyObject *wrap_info(PyObject *UNUSED(self), PyObject *args){
1357 int type;
1358 const char *name;
1359
1360 if (!policy) {
1361 PyErr_SetString(PyExc_RuntimeError,"Policy not loaded");
1362 return NULL;
1363 }
1364
1365 if (!PyArg_ParseTuple(args, "iz", &type, &name))
1366 return NULL;
1367
1368 return info(type, name);
1369 }
1370
init_info(PyObject * m)1371 void init_info (PyObject *m) {
1372 PyModule_AddIntConstant(m, "ATTRIBUTE", ATTRIBUTE);
1373 PyModule_AddIntConstant(m, "PORT", PORT);
1374 PyModule_AddIntConstant(m, "ROLE", ROLE);
1375 PyModule_AddIntConstant(m, "TYPE", TYPE);
1376 PyModule_AddIntConstant(m, "USER", USER);
1377 PyModule_AddIntConstant(m, "CLASS", CLASS);
1378 PyModule_AddIntConstant(m, "BOOLEAN", BOOLEAN);
1379 PyModule_AddIntConstant(m, "SENS", SENS);
1380 PyModule_AddIntConstant(m, "CATS", CATS);
1381 }
1382