Home | History | Annotate | Download | only in sepolicy
      1 /**
      2  *  @file
      3  *  Command line tool to search TE rules.
      4  *
      5  *  @author Frank Mayer  mayerf (at) tresys.com
      6  *  @author Jeremy A. Mowery jmowery (at) tresys.com
      7  *  @author Paul Rosenfeld  prosenfeld (at) tresys.com
      8  *  @author Thomas Liu  <tliu (at) redhat.com>
      9  *  @author Dan Walsh  <dwalsh (at) 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 
     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 
     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  */
     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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
   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  */
   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  */
   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  */
   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 
   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 
   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 
   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