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