Index: setools-3.3.6/configure.ac =================================================================== --- setools-3.3.6.orig/configure.ac +++ setools-3.3.6/configure.ac @@ -216,6 +216,9 @@ if test "x${enable_jswig}" = xyes; then do_swigify_java=yes do_swigify=yes fi + +AM_PATH_PYTHON(2.6) + AC_ARG_ENABLE(swig-python, AC_HELP_STRING([--enable-swig-python], [build SWIG interfaces for Python]), @@ -224,7 +227,6 @@ if test "x${enable_pyswig}" = xyes; then if test ${do_swigify} = no; then AC_PROG_SWIG(1.3.28) fi - AM_PATH_PYTHON(2.3) SWIG_PYTHON do_swigify_python=yes do_swigify=yes @@ -873,6 +875,8 @@ AC_CONFIG_FILES([Makefile VERSION \ sediff/Makefile \ man/Makefile \ debian/Makefile \ + python/Makefile \ + python/setools/Makefile \ packages/Makefile packages/rpm/Makefile \ packages/libqpol.pc packages/libapol.pc packages/libpoldiff.pc packages/libseaudit.pc packages/libsefs.pc]) Index: setools-3.3.6/Makefile.am =================================================================== --- setools-3.3.6.orig/Makefile.am +++ setools-3.3.6/Makefile.am @@ -10,7 +10,7 @@ if BUILD_GUI endif # sediffx is also built conditionally, from sediffx/Makefile.am -SUBDIRS = libqpol libapol libsefs libpoldiff libseaudit secmds sechecker sediff man packages debian $(MAYBE_APOL) $(MAYBE_GUI) +SUBDIRS = libqpol libapol libsefs libpoldiff libseaudit secmds sechecker sediff man packages debian $(MAYBE_APOL) $(MAYBE_GUI) python #old indent opts #INDENT_OPTS = -npro -nbad -bap -sob -ss -l132 -di1 -nbc -br -nbbb -c40 -cd40 -ncdb -ce -cli0 -cp40 -ncs -d0 -nfc1 -nfca -i8 -ts8 -ci8 -lp -ip0 -npcs -npsl -sc Index: setools-3.3.6/python/Makefile.am =================================================================== --- /dev/null +++ setools-3.3.6/python/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = setools Index: setools-3.3.6/python/setools/__init__.py =================================================================== --- /dev/null +++ setools-3.3.6/python/setools/__init__.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +# Author: Thomas Liu + +import _sesearch +import _seinfo +import types + +TYPE = _seinfo.TYPE +ROLE = _seinfo.ROLE +ATTRIBUTE = _seinfo.ATTRIBUTE +USER = _seinfo.USER + +ALLOW = 'allow' +AUDITALLOW = 'auditallow' +NEVERALLOW = 'neverallow' +DONTAUDIT = 'dontaudit' +SCONTEXT = 'scontext' +TCONTEXT = 'tcontext' +PERMS = 'permlist' +CLASS = 'class' + +def sesearch(types, info): + valid_types = [ALLOW, AUDITALLOW, NEVERALLOW, DONTAUDIT] + for type in types: + if type not in valid_types: + raise ValueError("Type has to be in %s" % valid_types) + info[type] = True + + perms = [] + if PERMS in info: + perms = info[PERMS] + info[PERMS] = ",".join(info[PERMS]) + + + dict_list = _sesearch.sesearch(info) + if len(perms) != 0: + dict_list = filter(lambda x: dict_has_perms(x, perms), dict_list) + return dict_list + +def dict_has_perms(dict, perms): + for perm in perms: + if perm not in dict[PERMS]: + return False + return True + +def seinfo(setype, name=None): + dict_list = _seinfo.seinfo(setype, name) + return dict_list Index: setools-3.3.6/python/setools/Makefile.am =================================================================== --- /dev/null +++ setools-3.3.6/python/setools/Makefile.am @@ -0,0 +1,36 @@ +EXTRA_DIST = \ + sesearch.c \ + seinfo.c \ + __init__.py \ + setup.py \ + $(NULL) + +AM_CFLAGS = @DEBUGCFLAGS@ @WARNCFLAGS@ @PROFILECFLAGS@ @SELINUX_CFLAGS@ \ + @QPOL_CFLAGS@ @APOL_CFLAGS@ +AM_CXXFLAGS = @DEBUGCXXFLAGS@ @WARNCXXFLAGS@ @PROFILECFLAGS@ @SELINUX_CFLAGS@ \ + @QPOL_CFLAGS@ @APOL_CFLAGS@ @SEFS_CFLAGS@ +AM_LDFLAGS = @DEBUGLDFLAGS@ @WARNLDFLAGS@ @PROFILELDFLAGS@ + +LDADD = @SELINUX_LIB_FLAG@ @APOL_LIB_FLAG@ @QPOL_LIB_FLAG@ +DEPENDENCIES = $(top_builddir)/libapol/src/libapol.so $(top_builddir)/libqpol/src/libqpol.so +all-am: python-build + +seinfo_SOURCES = seinfo.c + +sesearch_SOURCES = sesearch.c + +python-build: sesearch.c seinfo.c + @mkdir -p setools + @cp __init__.py setools + LIBS="$(QPOL_LIB_FLAG) $(APOL_LIB_FLAG)" INCLUDES="$(QPOL_CFLAGS) $(APOL_CFLAGS)" $(PYTHON) setup.py build + +install-exec-hook: + $(PYTHON) setup.py install `test -n "$(DESTDIR)" && echo --root $(DESTDIR)` + +uninstall-hook: + $(PYTHON) setup.py uninstall `test -n "$(DESTDIR)" && echo --root $(DESTDIR)` + +clean-local: + $(PYTHON) setup.py clean -a + rm -f *~ + Index: setools-3.3.6/python/setools/seinfo.c =================================================================== --- /dev/null +++ setools-3.3.6/python/setools/seinfo.c @@ -0,0 +1,649 @@ +/** + * @file + * Command line tool to search TE rules. + * + * @author Frank Mayer mayerf@tresys.com + * @author Jeremy A. Mowery jmowery@tresys.com + * @author Paul Rosenfeld prosenfeld@tresys.com + * @author Thomas Liu + * @author Dan Walsh + * + * Copyright (C) 2003-2008 Tresys Technology, LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * This is a modified version of seinfo to be used as part of a library for + * Python bindings. + */ + +#include "Python.h" + +/* libapol */ +#include +#include +#include +#include +#include + +/* libqpol */ +#include +#include + +/* other */ +#include +#include +#include +#include +#include + +#define COPYRIGHT_INFO "Copyright (C) 2003-2007 Tresys Technology, LLC" +static char *policy_file = NULL; + +enum input +{ + TYPE, ATTRIBUTE, ROLE, USER +}; + +/** + * Gets a textual representation of an attribute, and + * all of that attribute's types. + * + * @param type_datum Reference to sepol type_datum + * @param policydb Reference to a policy + */ +static PyObject* get_attr(const qpol_type_t * type_datum, const apol_policy_t * policydb) +{ + int retval = -1; + PyObject *dict = PyDict_New(); + const qpol_type_t *attr_datum = NULL; + qpol_iterator_t *iter = NULL; + const char *attr_name = NULL, *type_name = NULL; + qpol_policy_t *q = apol_policy_get_qpol(policydb); + unsigned char isattr; + + if (qpol_type_get_name(q, type_datum, &attr_name)) + goto cleanup; + PyObject *obj = PyString_FromString(attr_name); + PyDict_SetItemString(dict, "name", obj); + Py_DECREF(obj); + + /* get an iterator over all types this attribute has */ + if (qpol_type_get_isattr(q, type_datum, &isattr)) + goto cleanup; + if (isattr) { /* sanity check */ + if (qpol_type_get_type_iter(q, type_datum, &iter)) + goto cleanup; + PyObject *list = PyList_New(0); + for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { + if (qpol_iterator_get_item(iter, (void **)&attr_datum)) + goto cleanup; + if (qpol_type_get_name(q, attr_datum, &type_name)) + goto cleanup; + PyObject *obj = PyString_FromString(type_name); + PyList_Append(list, obj); + Py_DECREF(obj); + } + qpol_iterator_destroy(&iter); + PyDict_SetItemString(dict, "types", list); + Py_DECREF(list); + } else /* this should never happen */ + goto cleanup; + + retval = 0; +cleanup: + qpol_iterator_destroy(&iter); + if (retval) { + Py_DECREF(dict); + return NULL; + } + return dict; +} + +/** + * Gets statistics regarding a policy's attributes. + * If this function is given a name, it will attempt to + * get statistics about a particular attribute; otherwise + * the function gets statistics about all of the policy's + * attributes. + * + * @param name Reference to an attribute's name; if NULL, + * all object classes will be considered + * @param policydb Reference to a policy + * + * @return 0 on success, < 0 on error. + */ +static PyObject* get_attribs(const char *name, const apol_policy_t * policydb) +{ + int retval = -1; + PyObject *list = PyList_New(0); + apol_attr_query_t *attr_query = NULL; + apol_vector_t *v = NULL; + const qpol_type_t *type_datum = NULL; + size_t n_attrs, i; + + /* we are only getting information about 1 attribute */ + if (name != NULL) { + attr_query = apol_attr_query_create(); + if (!attr_query) + goto cleanup; + if (apol_attr_query_set_attr(policydb, attr_query, name)) + goto cleanup; + if (apol_attr_get_by_query(policydb, attr_query, &v)) + goto cleanup; + apol_attr_query_destroy(&attr_query); + if (apol_vector_get_size(v) == 0) { + apol_vector_destroy(&v); + errno = EINVAL; + goto cleanup; + } + + type_datum = apol_vector_get_element(v, (size_t) 0); + PyObject *obj = get_attr(type_datum, policydb); + PyList_Append(list, obj); + Py_DECREF(obj); + } else { + attr_query = apol_attr_query_create(); + if (!attr_query) + goto cleanup; + if (apol_attr_get_by_query(policydb, attr_query, &v)) + goto cleanup; + apol_attr_query_destroy(&attr_query); + n_attrs = apol_vector_get_size(v); + + for (i = 0; i < n_attrs; i++) { + /* get qpol_type_t* item from vector */ + type_datum = (qpol_type_t *) apol_vector_get_element(v, (size_t) i); + if (!type_datum) + goto cleanup; + PyObject *obj = get_attr(type_datum, policydb); + PyList_Append(list, obj); + Py_DECREF(obj); + } + } + apol_vector_destroy(&v); + + retval = 0; + cleanup: + apol_attr_query_destroy(&attr_query); + apol_vector_destroy(&v); + if (retval) { + Py_DECREF(list); + PyErr_SetString(PyExc_RuntimeError,strerror(errno)); + return NULL; + } + return list; +} + +/** + * Get a textual representation of a type, and + * all of that type's attributes. + * + * @param type_datum Reference to sepol type_datum + * @param policydb Reference to a policy + */ +static PyObject* get_type_attrs(const qpol_type_t * type_datum, const apol_policy_t * policydb) +{ + qpol_iterator_t *iter = NULL; + const char *attr_name = NULL; + const qpol_type_t *attr_datum = NULL; + qpol_policy_t *q = apol_policy_get_qpol(policydb); + + if (qpol_type_get_attr_iter(q, type_datum, &iter)) + goto cleanup; + PyObject *list = PyList_New(0); + for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { + if (qpol_iterator_get_item(iter, (void **)&attr_datum)) + goto cleanup; + if (qpol_type_get_name(q, attr_datum, &attr_name)) + goto cleanup; + PyObject *obj = PyString_FromString(attr_name); + PyList_Append(list, obj); + Py_DECREF(obj); + } + + cleanup: + qpol_iterator_destroy(&iter); + return list; +} + +static PyObject* get_type( const qpol_type_t * type_datum, const apol_policy_t * policydb) { + + PyObject *dict = PyDict_New(); + qpol_policy_t *q = apol_policy_get_qpol(policydb); + const char *type_name = NULL; + + unsigned char isalias, ispermissive, isattr; + + if (qpol_type_get_name(q, type_datum, &type_name)) + goto cleanup; + if (qpol_type_get_isalias(q, type_datum, &isalias)) + goto cleanup; + if (qpol_type_get_isattr(q, type_datum, &isattr)) + goto cleanup; + if (qpol_type_get_ispermissive(q, type_datum, &ispermissive)) + goto cleanup; + + PyObject *obj = PyString_FromString(type_name); + PyDict_SetItemString(dict, "name", obj); + Py_DECREF(obj); + obj = PyBool_FromLong(ispermissive); + PyDict_SetItemString(dict, "permissive", obj); + Py_DECREF(obj); + if (!isattr && !isalias) { + obj = get_type_attrs(type_datum, policydb); + PyDict_SetItemString(dict, "attributes", obj); + Py_DECREF(obj); + } + return dict; +cleanup: + Py_DECREF(dict); + return NULL; +} + +/** + * Gets a textual representation of a user, and + * all of that user's roles. + * + * @param type_datum Reference to sepol type_datum + * @param policydb Reference to a policy + * roles + */ +static PyObject* get_user(const qpol_user_t * user_datum, const apol_policy_t * policydb) +{ + PyObject *dict = NULL; + const qpol_role_t *role_datum = NULL; + qpol_iterator_t *iter = NULL; + const qpol_mls_range_t *range = NULL; + const qpol_mls_level_t *dflt_level = NULL; + apol_mls_level_t *ap_lvl = NULL; + apol_mls_range_t *ap_range = NULL; + qpol_policy_t *q = apol_policy_get_qpol(policydb); + char *tmp; + const char *user_name, *role_name; + + if (qpol_user_get_name(q, user_datum, &user_name)) + goto cleanup; + + dict = PyDict_New(); + PyObject *obj = PyString_FromString(user_name); + PyDict_SetItemString(dict, "name", obj); + Py_DECREF(obj); + + if (qpol_policy_has_capability(q, QPOL_CAP_MLS)) { + if (qpol_user_get_dfltlevel(q, user_datum, &dflt_level)) + goto cleanup; + ap_lvl = apol_mls_level_create_from_qpol_mls_level(policydb, dflt_level); + tmp = apol_mls_level_render(policydb, ap_lvl); + if (!tmp) + goto cleanup; + obj = PyString_FromString(tmp); + PyDict_SetItemString(dict, "level", obj); + Py_DECREF(obj); + free(tmp); + /* print default range */ + if (qpol_user_get_range(q, user_datum, &range)) + goto cleanup; + ap_range = apol_mls_range_create_from_qpol_mls_range(policydb, range); + tmp = apol_mls_range_render(policydb, ap_range); + if (!tmp) + goto cleanup; + obj = PyString_FromString(tmp); + PyDict_SetItemString(dict, "range", obj); + Py_DECREF(obj); + free(tmp); + } + + if (qpol_user_get_role_iter(q, user_datum, &iter)) + goto cleanup; + PyObject *list = PyList_New(0); + for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { + if (qpol_iterator_get_item(iter, (void **)&role_datum)) { + Py_DECREF(list); + goto cleanup; + } + if (qpol_role_get_name(q, role_datum, &role_name)) { + Py_DECREF(list); + goto cleanup; + } + PyObject *obj = PyString_FromString(role_name); + PyList_Append(list, obj); + Py_DECREF(obj); + } + PyDict_SetItemString(dict, "roles", list); + Py_DECREF(list); + +cleanup: + qpol_iterator_destroy(&iter); + apol_mls_level_destroy(&ap_lvl); + apol_mls_range_destroy(&ap_range); + return dict; +} + +/** + * Gets statistics regarding a policy's users. + * If this function is given a name, it will attempt to + * get statistics about a particular user; otherwise + * the function gets statistics about all of the policy's + * users. + * + * @param name Reference to a user's name; if NULL, + * all users will be considered + * @param policydb Reference to a policy + * + * @return 0 on success, < 0 on error. + */ +static PyObject* get_users(const char *name, const apol_policy_t * policydb) +{ + int retval = -1; + PyObject *list = PyList_New(0); + qpol_iterator_t *iter = NULL; + const qpol_user_t *user_datum = NULL; + qpol_policy_t *q = apol_policy_get_qpol(policydb); + + if (name != NULL) { + if (qpol_policy_get_user_by_name(q, name, &user_datum)) { + errno = EINVAL; + goto cleanup; + } + PyObject *obj = get_user(user_datum, policydb); + PyList_Append(list, obj); + Py_DECREF(obj); + } else { + if (qpol_policy_get_user_iter(q, &iter)) + goto cleanup; + + for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { + if (qpol_iterator_get_item(iter, (void **)&user_datum)) + goto cleanup; + PyObject *obj = get_user(user_datum, policydb); + PyList_Append(list, obj); + Py_DECREF(obj); + } + qpol_iterator_destroy(&iter); + } + + retval = 0; + cleanup: + qpol_iterator_destroy(&iter); + if (retval) { + Py_DECREF(list); + PyErr_SetString(PyExc_RuntimeError,strerror(errno)); + return NULL; + } + return list; +} + +/** + * get a textual representation of a role, and + * all of that role's types. + * + * @param type_datum Reference to sepol type_datum + * @param policydb Reference to a policy + * types + */ +static PyObject* get_role(const qpol_role_t * role_datum, const apol_policy_t * policydb) +{ + int retval = -1; + PyObject *dict = PyDict_New(); + const char *role_name = NULL, *type_name = NULL; + const qpol_role_t *dom_datum = NULL; + const qpol_type_t *type_datum = NULL; + qpol_iterator_t *iter = NULL; + qpol_policy_t *q = apol_policy_get_qpol(policydb); + size_t n_dom = 0, n_types = 0; + + if (qpol_role_get_name(q, role_datum, &role_name)) + goto cleanup; + + PyObject *obj = PyString_FromString(role_name); + PyDict_SetItemString(dict, "name", obj); + Py_DECREF(obj); + + if (qpol_role_get_dominate_iter(q, role_datum, &iter)) + goto cleanup; + if (qpol_iterator_get_size(iter, &n_dom)) + goto cleanup; + if ((int)n_dom > 0) { + PyObject *list = PyList_New(0); + for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { + if (qpol_iterator_get_item(iter, (void **)&dom_datum)) + goto cleanup; + if (qpol_role_get_name(q, dom_datum, &role_name)) + goto cleanup; + PyObject *obj = PyString_FromString(role_name); + PyList_Append(list, obj); + Py_DECREF(obj); + } + PyDict_SetItemString(dict, "dominate", list); + Py_DECREF(list); + } + qpol_iterator_destroy(&iter); + + if (qpol_role_get_type_iter(q, role_datum, &iter)) + goto cleanup; + if (qpol_iterator_get_size(iter, &n_types)) + goto cleanup; + if ((int)n_types > 0) { + PyObject *list = PyList_New(0); + /* print types */ + for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { + if (qpol_iterator_get_item(iter, (void **)&type_datum)) + goto cleanup; + if (qpol_type_get_name(q, type_datum, &type_name)) + goto cleanup; + PyObject *obj = PyString_FromString(type_name); + PyList_Append(list, obj); + Py_DECREF(obj); + } + PyDict_SetItemString(dict, "types", list); + Py_DECREF(list); + } + + retval = 0; +cleanup: + qpol_iterator_destroy(&iter); + if (retval) { + Py_DECREF(dict); + PyErr_SetString(PyExc_RuntimeError,strerror(errno)); + return NULL; + } + return dict; +} + +/** + * Get statistics regarding a policy's roles. + * If this function is given a name, it will attempt to + * get statistics about a particular role; otherwise + * the function get statistics about all of the policy's roles. + * + * @param name Reference to an role's name; if NULL, + * all roles will be considered + * @param policydb Reference to a policy + * + * @return 0 on success, < 0 on error. + */ +static PyObject* get_roles(const char *name, const apol_policy_t * policydb) +{ + int retval = -1; + PyObject *list = PyList_New(0); + const qpol_role_t *role_datum = NULL; + qpol_iterator_t *iter = NULL; + qpol_policy_t *q = apol_policy_get_qpol(policydb); + + if (name != NULL) { + if (qpol_policy_get_role_by_name(q, name, &role_datum)) { + errno = EINVAL; + goto cleanup; + } + PyObject *obj = get_role(role_datum, policydb); + PyList_Append(list, obj); + Py_DECREF(obj); + } else { + if (qpol_policy_get_role_iter(q, &iter)) + goto cleanup; + + for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { + if (qpol_iterator_get_item(iter, (void **)&role_datum)) + goto cleanup; + PyObject *obj = get_role(role_datum, policydb); + PyList_Append(list, obj); + Py_DECREF(obj); + } + qpol_iterator_destroy(&iter); + } + + retval = 0; + cleanup: + qpol_iterator_destroy(&iter); + if (retval) { + Py_DECREF(list); + PyErr_SetString(PyExc_RuntimeError,strerror(errno)); + return NULL; + } + return list; +} + +/** + * Get statistics regarding a policy's types. + * If this function is given a name, it will attempt to + * print statistics about a particular type; otherwise + * the function prints statistics about all of the policy's types. + * + * @param name Reference to a type's name; if NULL, + * all object classes will be considered + * @param policydb Reference to a policy + * + * @return 0 on success, < 0 on error. + */ +static PyObject* get_types(const char *name, const apol_policy_t * policydb) +{ + int retval = -1; + PyObject *list = PyList_New(0); + const qpol_type_t *type_datum = NULL; + qpol_iterator_t *iter = NULL; + qpol_policy_t *q = apol_policy_get_qpol(policydb); + + /* if name was provided, only print that name */ + if (name != NULL) { + if (qpol_policy_get_type_by_name(q, name, &type_datum)) { + errno = EINVAL; + goto cleanup; + } + PyObject *obj = get_type(type_datum, policydb); + PyList_Append(list, obj); + Py_DECREF(obj); + } else { + if (qpol_policy_get_type_iter(q, &iter)) + goto cleanup; + /* Print all type names */ + for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { + if (qpol_iterator_get_item(iter, (void **)&type_datum)) + goto cleanup; + PyObject *obj = get_type(type_datum, policydb); + PyList_Append(list, obj); + Py_DECREF(obj); + } + } + retval = 0; +cleanup: + qpol_iterator_destroy(&iter); + if (retval) { + Py_DECREF(list); + PyErr_SetString(PyExc_RuntimeError,strerror(errno)); + return NULL; + } + return list; +} + +PyObject* seinfo(int type, const char *name) +{ + int rt = -1; + + apol_policy_t *policydb = NULL; + apol_policy_path_t *pol_path = NULL; + apol_vector_t *mod_paths = NULL; + apol_policy_path_type_e path_type = APOL_POLICY_PATH_TYPE_MONOLITHIC; + PyObject* output = NULL; + + rt = qpol_default_policy_find(&policy_file); + if (rt != 0) { + PyErr_SetString(PyExc_RuntimeError,"No default policy found."); + return NULL; + } + + pol_path = apol_policy_path_create(path_type, policy_file, mod_paths); + if (!pol_path) { + free(policy_file); + apol_vector_destroy(&mod_paths); + PyErr_SetString(PyExc_RuntimeError,strerror(ENOMEM)); + return NULL; + } + apol_vector_destroy(&mod_paths); + + int policy_load_options = 0; + policy_load_options |= QPOL_POLICY_OPTION_MATCH_SYSTEM; + policydb = apol_policy_create_from_policy_path(pol_path, policy_load_options, NULL, NULL); + if (!policydb) { + free(policy_file); + apol_policy_path_destroy(&pol_path); + PyErr_SetString(PyExc_RuntimeError,strerror(errno)); + return NULL; + } + free(policy_file); + + /* display requested info */ + if (type == TYPE) + output = get_types(name, policydb); + + if (type == ATTRIBUTE) + output = get_attribs(name, policydb); + + if (type == ROLE) + output = get_roles(name, policydb); + + if (type == USER) + output = get_users(name, policydb); + + apol_policy_destroy(&policydb); + apol_policy_path_destroy(&pol_path); + return output; +} + +PyObject *wrap_seinfo(PyObject *self, PyObject *args){ + unsigned int type; + char *name; + + if (!PyArg_ParseTuple(args, "iz", &type, &name)) + return NULL; + + return Py_BuildValue("O",seinfo(type, name)); + +} + +static PyMethodDef methods[] = { + {"seinfo", (PyCFunction) wrap_seinfo, METH_VARARGS}, + {NULL, NULL, 0, NULL} +}; + +void init_seinfo(){ + PyObject *m; + m = Py_InitModule("_seinfo", methods); + PyModule_AddIntConstant(m, "ATTRIBUTE", ATTRIBUTE); + PyModule_AddIntConstant(m, "ROLE", ROLE); + PyModule_AddIntConstant(m, "TYPE", TYPE); + PyModule_AddIntConstant(m, "USER", USER); +} Index: setools-3.3.6/python/setools/sesearch.c =================================================================== --- /dev/null +++ setools-3.3.6/python/setools/sesearch.c @@ -0,0 +1,477 @@ +// Author: Thomas Liu + +/** + * @file + * Command line tool to search TE rules. + * + * @author Frank Mayer mayerf@tresys.com + * @author Jeremy A. Mowery jmowery@tresys.com + * @author Paul Rosenfeld prosenfeld@tresys.com + * @author Thomas Liu + * + * Copyright (C) 2003-2008 Tresys Technology, LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * This is a modified version of sesearch to be used as part of a library for + * Python bindings. + */ + +#include "Python.h" + +/* libapol */ +#include +#include +#include +#include +#include + +/* libqpol*/ +#include +#include +#include +#include + +/* other */ +#include +#include +#include +#include +#include +#include +#include + +#define COPYRIGHT_INFO "Copyright (C) 2003-2007 Tresys Technology, LLC" +static char *policy_file = NULL; + +enum opt_values +{ + RULE_NEVERALLOW = 256, RULE_AUDIT, RULE_AUDITALLOW, RULE_DONTAUDIT, + RULE_ROLE_ALLOW, RULE_ROLE_TRANS, RULE_RANGE_TRANS, RULE_ALL, + EXPR_ROLE_SOURCE, EXPR_ROLE_TARGET +}; + +; + +typedef struct options +{ + char *src_name; + char *tgt_name; + char *src_role_name; + char *tgt_role_name; + char *class_name; + char *permlist; + char *bool_name; + apol_vector_t *class_vector; + bool all; + bool lineno; + bool semantic; + bool indirect; + bool allow; + bool nallow; + bool auditallow; + bool dontaudit; + bool type; + bool rtrans; + bool role_allow; + bool role_trans; + bool useregex; + bool show_cond; + apol_vector_t *perm_vector; +} options_t; + +static int perform_av_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v) +{ + apol_avrule_query_t *avq = NULL; + unsigned int rules = 0; + int error = 0; + char *tmp = NULL, *tok = NULL, *s = NULL; + + if (!policy || !opt || !v) { + PyErr_SetString(PyExc_RuntimeError,strerror(EINVAL)); + errno = EINVAL; + return -1; + } + + if (!opt->all && !opt->allow && !opt->nallow && !opt->auditallow && !opt->dontaudit) { + *v = NULL; + return 0; /* no search to do */ + } + + avq = apol_avrule_query_create(); + if (!avq) { + PyErr_SetString(PyExc_RuntimeError,strerror(ENOMEM)); + errno = ENOMEM; + return -1; + } + + if (opt->allow || opt->all) + rules |= QPOL_RULE_ALLOW; + if ((opt->nallow || opt->all) && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_NEVERALLOW)) + rules |= QPOL_RULE_NEVERALLOW; + if (opt->auditallow || opt->all) + rules |= QPOL_RULE_AUDITALLOW; + if (opt->dontaudit || opt->all) + rules |= QPOL_RULE_DONTAUDIT; + apol_avrule_query_set_rules(policy, avq, rules); + apol_avrule_query_set_regex(policy, avq, opt->useregex); + if (opt->src_name) + apol_avrule_query_set_source(policy, avq, opt->src_name, opt->indirect); + if (opt->tgt_name) + apol_avrule_query_set_target(policy, avq, opt->tgt_name, opt->indirect); + if (opt->bool_name) + apol_avrule_query_set_bool(policy, avq, opt->bool_name); + if (opt->class_name) { + if (opt->class_vector == NULL) { + if (apol_avrule_query_append_class(policy, avq, opt->class_name)) { + error = errno; + goto err; + } + } else { + size_t i; + for (i = 0; i < apol_vector_get_size(opt->class_vector); ++i) { + char *class_name; + class_name = apol_vector_get_element(opt->class_vector, i); + if (!class_name) + continue; + if (apol_avrule_query_append_class(policy, avq, class_name)) { + error = errno; + goto err; + } + } + } + } + + if (opt->permlist) { + tmp = strdup(opt->permlist); + for (tok = strtok(tmp, ","); tok; tok = strtok(NULL, ",")) { + if (apol_avrule_query_append_perm(policy, avq, tok)) { + error = errno; + goto err; + } + if ((s = strdup(tok)) == NULL || apol_vector_append(opt->perm_vector, s) < 0) { + error = errno; + goto err; + } + s = NULL; + } + free(tmp); + } + + if (!(opt->semantic) && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) { + if (apol_syn_avrule_get_by_query(policy, avq, v)) { + error = errno; + goto err; + } + } else { + if (apol_avrule_get_by_query(policy, avq, v)) { + error = errno; + goto err; + } + } + + apol_avrule_query_destroy(&avq); + return 0; + + err: + apol_vector_destroy(v); + apol_avrule_query_destroy(&avq); + free(tmp); + free(s); + PyErr_SetString(PyExc_RuntimeError,strerror(error)); + errno = error; + return -1; +} + + + +static PyObject* get_av_results(const apol_policy_t * policy, const options_t * opt, const apol_vector_t * v) +{ + int retval = -1; + PyObject *list = PyList_New(0); + qpol_policy_t *q = apol_policy_get_qpol(policy); + size_t i, num_rules = 0; + const qpol_avrule_t *rule = NULL; + char *tmp = NULL, *rule_str = NULL, *expr = NULL; + char enable_char = ' ', branch_char = ' '; + qpol_iterator_t *iter = NULL; + uint32_t enabled = 0; + + if (!policy || !v) + return NULL; + + if (!(num_rules = apol_vector_get_size(v))) + return NULL; + + for (i = 0; i < num_rules; i++) { + enable_char = branch_char = ' '; + if (!(rule = apol_vector_get_element(v, i))) + goto cleanup; + + if (qpol_avrule_get_is_enabled(q, rule, &enabled)) + goto cleanup; + if (!enabled) + continue; + + const qpol_type_t *type; + const char *tmp_name; + uint32_t rule_type = 0; + + const qpol_class_t *obj_class = NULL; + + PyObject *dict = PyDict_New(); + + qpol_avrule_get_rule_type(q, rule, &rule_type); + tmp_name = apol_rule_type_to_str(rule_type); + PyObject *obj = PyString_FromString(tmp_name); + PyDict_SetItemString(dict, "type", obj); + Py_DECREF(obj); + // source + qpol_avrule_get_source_type(q, rule, &type); + qpol_type_get_name(q, type, &tmp_name); + obj = PyString_FromString(tmp_name); + PyDict_SetItemString(dict, "scontext", obj); + Py_DECREF(obj); + + qpol_avrule_get_target_type(q, rule, &type); + qpol_type_get_name(q, type, &tmp_name); + obj = PyString_FromString(tmp_name); + PyDict_SetItemString(dict, "tcontext", obj); + Py_DECREF(obj); + + qpol_avrule_get_object_class(q, rule, &obj_class); + qpol_type_get_name(q, type, &tmp_name); + obj = PyString_FromString(tmp_name); + PyDict_SetItemString(dict, "class", obj); + Py_DECREF(obj); + qpol_avrule_get_perm_iter(q, rule, &iter); + PyObject *permlist = PyList_New(0); + for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { + const char *perm_name = NULL; + qpol_iterator_get_item(iter, (void **)&perm_name); + obj = PyString_FromString(perm_name); + PyList_Append(permlist, obj); + Py_DECREF(obj); + } + PyDict_SetItemString(dict, "permlist", permlist); + Py_DECREF(permlist); + PyList_Append(list, dict); + Py_DECREF(dict); + + free(rule_str); + rule_str = NULL; + free(expr); + expr = NULL; + } + retval = 0; + cleanup: + free(tmp); + free(rule_str); + free(expr); + if (retval) { + Py_DECREF(list); + return NULL; + } + return list; +} + + +PyObject* sesearch(bool allow, + bool neverallow, + bool auditallow, + bool dontaudit, + const char *src_name, + const char *tgt_name, + const char *class_name, + const char *permlist + ) +{ + options_t cmd_opts; + int rt = -1; + PyObject *output = NULL; + + apol_policy_t *policy = NULL; + apol_vector_t *v = NULL; + apol_policy_path_t *pol_path = NULL; + apol_vector_t *mod_paths = NULL; + apol_policy_path_type_e path_type = APOL_POLICY_PATH_TYPE_MONOLITHIC; + + memset(&cmd_opts, 0, sizeof(cmd_opts)); + cmd_opts.indirect = true; + cmd_opts.allow = allow; + cmd_opts.nallow = neverallow; + cmd_opts.auditallow = auditallow; + cmd_opts.dontaudit = dontaudit; + if (src_name) + cmd_opts.src_name = strdup(src_name); + if (tgt_name) + cmd_opts.tgt_name = strdup(tgt_name); + if (class_name) + cmd_opts.class_name = strdup(class_name); + if (permlist){ + cmd_opts.perm_vector = apol_vector_create(free); + cmd_opts.permlist = strdup(permlist); + } + int pol_opt = 0; + if (!(cmd_opts.nallow || cmd_opts.all)) + pol_opt |= QPOL_POLICY_OPTION_NO_NEVERALLOWS; + + + rt = qpol_default_policy_find(&policy_file); + if (rt) { + PyErr_SetString(PyExc_RuntimeError,"No default policy found."); + return NULL; + } + pol_opt |= QPOL_POLICY_OPTION_MATCH_SYSTEM; + + if (apol_file_is_policy_path_list(policy_file) > 0) { + pol_path = apol_policy_path_create_from_file(policy_file); + if (!pol_path) { + free(policy_file); + PyErr_SetString(PyExc_RuntimeError,"invalid policy list"); + return NULL; + } + } + + if (!pol_path) + pol_path = apol_policy_path_create(path_type, policy_file, mod_paths); + if (!pol_path) { + free(policy_file); + PyErr_SetString(PyExc_RuntimeError,strerror(ENOMEM)); + return NULL; + } + free(policy_file); + apol_vector_destroy(&mod_paths); + + policy = apol_policy_create_from_policy_path(pol_path, pol_opt, NULL, NULL); + if (!policy) { + apol_policy_path_destroy(&pol_path); + PyErr_SetString(PyExc_RuntimeError,strerror(errno)); + return NULL; + } + /* handle regex for class name */ + if (cmd_opts.useregex && cmd_opts.class_name != NULL) { + cmd_opts.class_vector = apol_vector_create(NULL); + apol_vector_t *qpol_matching_classes = NULL; + apol_class_query_t *regex_match_query = apol_class_query_create(); + apol_class_query_set_regex(policy, regex_match_query, 1); + apol_class_query_set_class(policy, regex_match_query, cmd_opts.class_name); + if (apol_class_get_by_query(policy, regex_match_query, &qpol_matching_classes)) { + apol_class_query_destroy(®ex_match_query); + PyErr_SetString(PyExc_RuntimeError,"Query failed"); + goto cleanup; + } + const qpol_class_t *class = NULL; + size_t i; + for (i = 0; i < apol_vector_get_size(qpol_matching_classes); ++i) { + const char *class_name; + class = apol_vector_get_element(qpol_matching_classes, i); + if (!class) + break; + qpol_class_get_name(apol_policy_get_qpol(policy), class, &class_name); + apol_vector_append(cmd_opts.class_vector, (void *)class_name); + } + if (!apol_vector_get_size(qpol_matching_classes)) { + apol_vector_destroy(&qpol_matching_classes); + apol_class_query_destroy(®ex_match_query); + PyErr_SetString(PyExc_RuntimeError,"No classes match expression"); + goto cleanup; + } + apol_vector_destroy(&qpol_matching_classes); + apol_class_query_destroy(®ex_match_query); + } + + if (!cmd_opts.semantic && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) { + if (qpol_policy_build_syn_rule_table(apol_policy_get_qpol(policy))) { + apol_policy_destroy(&policy); + PyErr_SetString(PyExc_RuntimeError,"Query failed"); + goto cleanup; + } + } + + /* if syntactic rules are not available always do semantic search */ + if (!qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) { + cmd_opts.semantic = 1; + } + + /* supress line numbers if doing semantic search or not available */ + if (cmd_opts.semantic || !qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_LINE_NUMBERS)) { + cmd_opts.lineno = 0; + } + if (perform_av_query(policy, &cmd_opts, &v)) { + goto cleanup; + } + if (v) { + output = get_av_results(policy, &cmd_opts, v); + } + apol_vector_destroy(&v); + cleanup: + apol_policy_destroy(&policy); + apol_policy_path_destroy(&pol_path); + free(cmd_opts.src_name); + free(cmd_opts.tgt_name); + free(cmd_opts.class_name); + free(cmd_opts.permlist); + free(cmd_opts.bool_name); + free(cmd_opts.src_role_name); + free(cmd_opts.tgt_role_name); + apol_vector_destroy(&cmd_opts.perm_vector); + apol_vector_destroy(&cmd_opts.class_vector); + + return output; +} +static int Dict_ContainsInt(PyObject *dict, const char *key){ + PyObject *item = PyDict_GetItemString(dict, key); + if (item) + return PyInt_AsLong(item); + return false; +} + +static const char *Dict_ContainsString(PyObject *dict, const char *key){ + PyObject *item = PyDict_GetItemString(dict, key); + if (item) + return PyString_AsString(item); + return NULL; +} + +PyObject *wrap_sesearch(PyObject *self, PyObject *args){ + PyObject *dict; + if (!PyArg_ParseTuple(args, "O", &dict)) + return NULL; + int allow = Dict_ContainsInt(dict, "allow"); + int neverallow = Dict_ContainsInt(dict, "neverallow"); + int auditallow = Dict_ContainsInt(dict, "auditallow"); + int dontaudit = Dict_ContainsInt(dict, "dontaudit"); + + const char *src_name = Dict_ContainsString(dict, "scontext"); + const char *tgt_name = Dict_ContainsString(dict, "tcontext"); + const char *class_name = Dict_ContainsString(dict, "class"); + const char *permlist = Dict_ContainsString(dict, "permlist"); + + return Py_BuildValue("O",sesearch(allow, neverallow, auditallow, dontaudit, src_name, tgt_name, class_name, permlist)); + +} + +static PyMethodDef methods[] = { + {"sesearch", (PyCFunction) wrap_sesearch, METH_VARARGS}, + {NULL, NULL, 0, NULL} +}; + +void init_sesearch(){ + PyObject *m; + m = Py_InitModule("_sesearch", methods); +} Index: setools-3.3.6/python/setools/setup.py =================================================================== --- /dev/null +++ setools-3.3.6/python/setools/setup.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +# Author: Thomas Liu +import os +from distutils.core import setup, Extension +LIBS=["apol", "qpol"] + +try: + inc=os.getenv("INCLUDES").split(" ") + INCLUDES=map(lambda x: x[2:], inc) + LIBDIRS=map(lambda x: "/".join(x.split("/")[:-1]), os.getenv("LIBS").split()) +except: + INCLUDES="" + LIBDIRS="" + +extension_sesearch = Extension("setools._sesearch", [ "sesearch.c"]) +extension_sesearch.include_dirs=INCLUDES +extension_sesearch.libraries=LIBS +extension_sesearch.library_dirs=LIBDIRS +extension_seinfo = Extension("setools._seinfo", [ "seinfo.c"]) +extension_seinfo.include_dirs=INCLUDES +extension_seinfo.libraries=LIBS +extension_seinfo.library_dirs=LIBDIRS + +setup(name = "setools", version="1.0", description="Python setools bindings", author="Thomas Liu", author_email="tliu@redhat.com", ext_modules=[extension_sesearch, extension_seinfo], packages=["setools"])