1030 lines
24 KiB
C
1030 lines
24 KiB
C
// Author: Thomas Liu <tliu@redhat.com>
|
|
|
|
/**
|
|
* @file
|
|
* Python bindings used to search TE rules.
|
|
*
|
|
* @author Thomas Liu <tliu@redhat.com>
|
|
* @author Dan Walsh <dwalsh@redhat.com>
|
|
* Copyright (C) 2012-2013 Red Hat, inc
|
|
*
|
|
* Sections copied from sesearch.c in setools package
|
|
* @author Frank Mayer mayerf@tresys.com
|
|
* @author Jeremy A. Mowery jmowery@tresys.com
|
|
* @author Paul Rosenfeld prosenfeld@tresys.com
|
|
* 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 sepython library for
|
|
* Python bindings.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "policy.h"
|
|
|
|
/* libapol */
|
|
#include <apol/policy-query.h>
|
|
#include <apol/render.h>
|
|
#include <apol/util.h>
|
|
#include <apol/vector.h>
|
|
|
|
/* libqpol*/
|
|
#include <qpol/policy.h>
|
|
#include <qpol/policy_extend.h>
|
|
#include <qpol/syn_rule_query.h>
|
|
#include <qpol/util.h>
|
|
|
|
/* other */
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <getopt.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
|
|
#define COPYRIGHT_INFO "Copyright (C) 2012 Red Hat, Inc, Tresys Technology, LLC"
|
|
|
|
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 py_tuple_insert_obj(PyObject *tuple, int pos, PyObject *obj)
|
|
{
|
|
int rt;
|
|
if (!obj) return -1;
|
|
rt = PyTuple_SetItem(tuple, pos, obj);
|
|
return rt;
|
|
}
|
|
|
|
static int perform_ra_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v)
|
|
{
|
|
apol_role_allow_query_t *raq = NULL;
|
|
int error = 0;
|
|
|
|
if (!policy || !opt || !v) {
|
|
ERR(policy, "%s", strerror(EINVAL));
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
if (!opt->role_allow && !opt->all) {
|
|
*v = NULL;
|
|
return 0; /* no search to do */
|
|
}
|
|
|
|
raq = apol_role_allow_query_create();
|
|
if (!raq) {
|
|
ERR(policy, "%s", strerror(ENOMEM));
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
|
|
apol_role_allow_query_set_regex(policy, raq, opt->useregex);
|
|
if (opt->src_role_name) {
|
|
if (apol_role_allow_query_set_source(policy, raq, opt->src_role_name)) {
|
|
error = errno;
|
|
goto err;
|
|
}
|
|
}
|
|
if (opt->tgt_role_name)
|
|
if (apol_role_allow_query_set_target(policy, raq, opt->tgt_role_name)) {
|
|
error = errno;
|
|
goto err;
|
|
}
|
|
|
|
if (apol_role_allow_get_by_query(policy, raq, v)) {
|
|
error = errno;
|
|
goto err;
|
|
}
|
|
apol_role_allow_query_destroy(&raq);
|
|
return 0;
|
|
|
|
err:
|
|
apol_vector_destroy(v);
|
|
apol_role_allow_query_destroy(&raq);
|
|
ERR(policy, "%s", strerror(error));
|
|
errno = error;
|
|
return -1;
|
|
}
|
|
|
|
static PyObject* get_ra_results(const apol_policy_t * policy, const apol_vector_t * v, PyObject *output)
|
|
{
|
|
size_t i, num_rules = 0;
|
|
qpol_policy_t *q;
|
|
const qpol_role_allow_t *rule = NULL;
|
|
const char *tmp;
|
|
PyObject *obj, *dict=NULL;
|
|
const qpol_role_t *role = NULL;
|
|
int error = 0;
|
|
errno = EINVAL;
|
|
int rt;
|
|
|
|
if (!policy || !v) {
|
|
errno = EINVAL;
|
|
goto err;
|
|
}
|
|
|
|
if (!(num_rules = apol_vector_get_size(v)))
|
|
return NULL;
|
|
|
|
q = apol_policy_get_qpol(policy);
|
|
|
|
for (i = 0; i < num_rules; i++) {
|
|
dict = PyDict_New();
|
|
if (!dict) goto err;
|
|
if (!(rule = apol_vector_get_element(v, i)))
|
|
goto err;
|
|
|
|
if (qpol_role_allow_get_source_role(q, rule, &role)) {
|
|
goto err;
|
|
}
|
|
if (qpol_role_get_name(q, role, &tmp)) {
|
|
goto err;
|
|
}
|
|
obj = PyString_FromString(tmp);
|
|
if (py_insert_obj(dict, "source", obj))
|
|
goto err;
|
|
|
|
if (qpol_role_allow_get_target_role(q, rule, &role)) {
|
|
goto err;
|
|
}
|
|
if (qpol_role_get_name(q, role, &tmp)) {
|
|
goto err;
|
|
}
|
|
obj = PyString_FromString(tmp);
|
|
if (py_insert_obj(dict, "target", obj))
|
|
goto err;
|
|
|
|
rt = py_append_obj(output, dict);
|
|
if (rt) goto err;
|
|
py_decref(dict); dict=NULL;
|
|
}
|
|
goto cleanup;
|
|
err:
|
|
error = errno;
|
|
PyErr_SetString(PyExc_RuntimeError,strerror(error));
|
|
py_decref(dict);
|
|
|
|
cleanup:
|
|
errno = error;
|
|
return output;
|
|
}
|
|
|
|
static int perform_te_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v)
|
|
{
|
|
apol_terule_query_t *teq = NULL;
|
|
unsigned int rules = 0;
|
|
int error = 0;
|
|
size_t i;
|
|
|
|
if (!policy || !opt || !v) {
|
|
PyErr_SetString(PyExc_RuntimeError,strerror(EINVAL));
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
if (opt->all || opt->type) {
|
|
rules = (QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_CHANGE | QPOL_RULE_TYPE_MEMBER);
|
|
} else {
|
|
*v = NULL;
|
|
return 0; /* no search to do */
|
|
}
|
|
|
|
teq = apol_terule_query_create();
|
|
if (!teq) {
|
|
PyErr_SetString(PyExc_RuntimeError,strerror(ENOMEM));
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
|
|
apol_terule_query_set_rules(policy, teq, rules);
|
|
apol_terule_query_set_regex(policy, teq, opt->useregex);
|
|
|
|
if (opt->src_name)
|
|
apol_terule_query_set_source(policy, teq, opt->src_name, opt->indirect);
|
|
if (opt->tgt_name)
|
|
apol_terule_query_set_target(policy, teq, opt->tgt_name, opt->indirect);
|
|
if (opt->bool_name)
|
|
apol_terule_query_set_bool(policy, teq, opt->bool_name);
|
|
if (opt->class_name) {
|
|
if (opt->class_vector == NULL) {
|
|
if (apol_terule_query_append_class(policy, teq, opt->class_name)) {
|
|
error = errno;
|
|
goto err;
|
|
}
|
|
} else {
|
|
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_terule_query_append_class(policy, teq, class_name)) {
|
|
error = errno;
|
|
goto err;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!(opt->semantic) && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) {
|
|
if (apol_syn_terule_get_by_query(policy, teq, v)) {
|
|
goto err;
|
|
}
|
|
} else {
|
|
if (apol_terule_get_by_query(policy, teq, v)) {
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
apol_terule_query_destroy(&teq);
|
|
return 0;
|
|
|
|
err:
|
|
error = errno;
|
|
PyErr_SetString(PyExc_RuntimeError,strerror(error));
|
|
apol_vector_destroy(v);
|
|
apol_terule_query_destroy(&teq);
|
|
errno = error;
|
|
return -1;
|
|
}
|
|
|
|
static PyObject* get_bool(const qpol_policy_t *q, const qpol_cond_t * cond, int enabled)
|
|
{
|
|
qpol_iterator_t *iter = NULL;
|
|
qpol_cond_expr_node_t *expr = NULL;
|
|
char *tmp = NULL;
|
|
const char *bool_name = NULL;
|
|
int error = 0;
|
|
uint32_t expr_type = 0;
|
|
qpol_bool_t *cond_bool = NULL;
|
|
PyObject *obj, *tuple = NULL;
|
|
PyObject *boollist = NULL;
|
|
|
|
if (!q || !cond) {
|
|
errno = EINVAL;
|
|
return NULL;
|
|
}
|
|
if (qpol_cond_get_expr_node_iter(q, cond, &iter) < 0) {
|
|
goto err;
|
|
}
|
|
|
|
boollist = PyList_New(0);
|
|
if (! boollist) goto err;
|
|
|
|
for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
|
|
if (qpol_iterator_get_item(iter, (void **)&expr)) {
|
|
goto err;
|
|
}
|
|
if (qpol_cond_expr_node_get_expr_type(q, expr, &expr_type)) {
|
|
goto err;
|
|
}
|
|
if (expr_type != QPOL_COND_EXPR_BOOL) {
|
|
obj = PyString_FromString(apol_cond_expr_type_to_str(expr_type));
|
|
if (!obj) goto err;
|
|
if (py_append_obj(boollist, obj))
|
|
goto err;
|
|
} else {
|
|
tuple = PyTuple_New(2);
|
|
if (!tuple) goto err;
|
|
|
|
if (qpol_cond_expr_node_get_bool(q, expr, &cond_bool)) {
|
|
goto err;
|
|
}
|
|
if (qpol_bool_get_name(q, cond_bool, &bool_name)) {
|
|
goto err;
|
|
}
|
|
obj = PyString_FromString(bool_name);
|
|
if (py_tuple_insert_obj(tuple, 0, obj))
|
|
goto err;
|
|
obj = PyBool_FromLong(enabled);
|
|
if (py_tuple_insert_obj(tuple, 1, obj))
|
|
goto err;
|
|
if (py_append_obj(boollist, tuple))
|
|
goto err;
|
|
tuple=NULL;
|
|
}
|
|
}
|
|
|
|
qpol_iterator_destroy(&iter);
|
|
return boollist;
|
|
|
|
err:
|
|
error = errno;
|
|
qpol_iterator_destroy(&iter);
|
|
py_decref(tuple);
|
|
py_decref(boollist);
|
|
free(tmp);
|
|
errno = error;
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject* get_te_results(const apol_policy_t * policy, const apol_vector_t * v, PyObject *output)
|
|
{
|
|
int error = 0;
|
|
int rt = 0;
|
|
PyObject *obj, *dict=NULL, *tuple = NULL;
|
|
qpol_policy_t *q;
|
|
uint32_t rule_type = 0;
|
|
const qpol_type_t *type;
|
|
size_t i, num_rules = 0;
|
|
const qpol_terule_t *rule = NULL;
|
|
char *tmp = NULL, *rule_str = NULL, *expr = NULL;
|
|
const qpol_cond_t *cond = NULL;
|
|
uint32_t enabled = 0;
|
|
const char *tmp_name;
|
|
const qpol_class_t *obj_class = NULL;
|
|
|
|
if (!policy || !v) {
|
|
errno = EINVAL;
|
|
goto err;
|
|
}
|
|
|
|
if (!(num_rules = apol_vector_get_size(v)))
|
|
return NULL;
|
|
|
|
q = apol_policy_get_qpol(policy);
|
|
|
|
for (i = 0; i < num_rules; i++) {
|
|
dict = PyDict_New();
|
|
if (!dict) goto err;
|
|
if (!(rule = apol_vector_get_element(v, i)))
|
|
goto err;
|
|
if (qpol_terule_get_cond(q, rule, &cond))
|
|
goto err;
|
|
if (qpol_terule_get_is_enabled(q, rule, &enabled))
|
|
goto err;
|
|
|
|
if (cond) {
|
|
obj = get_bool(q, cond, enabled);
|
|
if (!obj) goto err;
|
|
rt = PyDict_SetItemString(dict, "boolean", obj);
|
|
py_decref(obj);
|
|
}
|
|
|
|
if (qpol_terule_get_rule_type(q, rule, &rule_type))
|
|
goto err;
|
|
|
|
if (!(rule_type &= (QPOL_RULE_TYPE_TRANS | QPOL_RULE_TYPE_CHANGE | QPOL_RULE_TYPE_MEMBER))) {
|
|
PyErr_SetString(PyExc_RuntimeError,"Invalid TE rule type");
|
|
errno = EINVAL;
|
|
goto err;
|
|
}
|
|
if (!(tmp_name = apol_rule_type_to_str(rule_type))) {
|
|
PyErr_SetString(PyExc_RuntimeError, "Could not get TE rule type's string");
|
|
errno = EINVAL;
|
|
goto err;
|
|
}
|
|
|
|
if (py_insert_string(dict, "type", tmp_name))
|
|
goto err;
|
|
|
|
if (qpol_terule_get_source_type(q, rule, &type))
|
|
goto err;
|
|
if (qpol_type_get_name(q, type, &tmp_name))
|
|
goto err;
|
|
if (py_insert_string(dict, "source", tmp_name))
|
|
goto err;
|
|
|
|
if (qpol_terule_get_target_type(q, rule, &type))
|
|
goto err;
|
|
if (qpol_type_get_name(q, type, &tmp_name))
|
|
goto err;
|
|
if (py_insert_string(dict, "target", tmp_name))
|
|
goto err;
|
|
|
|
if (qpol_terule_get_object_class(q, rule, &obj_class))
|
|
goto err;
|
|
if (qpol_class_get_name(q, obj_class, &tmp_name))
|
|
goto err;
|
|
if (py_insert_string(dict, "class", tmp_name))
|
|
goto err;
|
|
|
|
if (qpol_terule_get_default_type(q, rule, &type))
|
|
goto err;
|
|
if (qpol_type_get_name(q, type, &tmp_name))
|
|
goto err;
|
|
if (py_insert_string(dict, "transtype", tmp_name))
|
|
goto err;
|
|
|
|
rt = py_append_obj(output, dict);
|
|
dict = NULL;
|
|
if(rt) goto err;
|
|
|
|
free(rule_str); rule_str = NULL;
|
|
free(expr); expr = NULL;
|
|
}
|
|
goto cleanup;
|
|
|
|
err:
|
|
error = errno;
|
|
py_decref(dict);
|
|
py_decref(tuple);
|
|
PyErr_SetString(PyExc_RuntimeError,strerror(error));
|
|
cleanup:
|
|
free(tmp);
|
|
free(rule_str);
|
|
free(expr);
|
|
errno = error;
|
|
return output;
|
|
}
|
|
|
|
static int perform_ft_query(const apol_policy_t * policy, const options_t * opt, apol_vector_t ** v)
|
|
{
|
|
apol_filename_trans_query_t *ftq = NULL;
|
|
size_t i;
|
|
int error = 0;
|
|
|
|
if (!policy || !opt || !v) {
|
|
PyErr_SetString(PyExc_RuntimeError,strerror(EINVAL));
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
if (!opt->type && !opt->all) {
|
|
*v = NULL;
|
|
return 0; /* no search to do */
|
|
}
|
|
|
|
ftq = apol_filename_trans_query_create();
|
|
if (!ftq) {
|
|
PyErr_SetString(PyExc_RuntimeError,strerror(ENOMEM));
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
|
|
apol_filename_trans_query_set_regex(policy, ftq, opt->useregex);
|
|
if (opt->src_name) {
|
|
if (apol_filename_trans_query_set_source(policy, ftq, opt->src_name, opt->indirect)) {
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
if (opt->tgt_name) {
|
|
if (apol_filename_trans_query_set_target(policy, ftq, opt->tgt_name, opt->indirect)) {
|
|
goto err;
|
|
}
|
|
}
|
|
if (opt->class_name) {
|
|
if (opt->class_vector == NULL) {
|
|
if (apol_filename_trans_query_append_class(policy, ftq, opt->class_name)) {
|
|
goto err;
|
|
}
|
|
} else {
|
|
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_filename_trans_query_append_class(policy, ftq, class_name)) {
|
|
goto err;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (apol_filename_trans_get_by_query(policy, ftq, v))
|
|
goto err;
|
|
|
|
apol_filename_trans_query_destroy(&ftq);
|
|
return 0;
|
|
|
|
err:
|
|
error = errno;
|
|
PyErr_SetString(PyExc_RuntimeError,strerror(errno));
|
|
apol_vector_destroy(v);
|
|
apol_filename_trans_query_destroy(&ftq);
|
|
errno = error;
|
|
return -1;
|
|
}
|
|
|
|
static PyObject* get_ft_results(const apol_policy_t * policy, const apol_vector_t * v, PyObject *list)
|
|
{
|
|
PyObject *dict = NULL;
|
|
size_t i, num_filename_trans = 0;
|
|
const char *tmp_name;
|
|
int error = 0;
|
|
int rt;
|
|
const qpol_filename_trans_t *filename_trans = NULL;
|
|
const qpol_class_t *obj_class = NULL;
|
|
char *tmp = NULL, *filename_trans_str = NULL, *expr = NULL;
|
|
qpol_policy_t *q;
|
|
const qpol_type_t *type = NULL;
|
|
|
|
if (!policy || !v) {
|
|
errno = EINVAL;
|
|
goto err;
|
|
}
|
|
|
|
if (!(num_filename_trans = apol_vector_get_size(v)))
|
|
return NULL;
|
|
|
|
q = apol_policy_get_qpol(policy);
|
|
|
|
for (i = 0; i < num_filename_trans; i++) {
|
|
if (!(filename_trans = apol_vector_get_element(v, i)))
|
|
goto err;
|
|
|
|
dict = PyDict_New();
|
|
if (!dict) goto err;
|
|
|
|
if (py_insert_string(dict, "type", "type_transition"))
|
|
goto err;
|
|
|
|
/* source type */
|
|
if (qpol_filename_trans_get_source_type(q, filename_trans, &type)) {
|
|
goto err;
|
|
}
|
|
if (qpol_type_get_name(q, type, &tmp_name)) {
|
|
goto err;
|
|
}
|
|
|
|
if (py_insert_string(dict, "source", tmp_name))
|
|
goto err;
|
|
|
|
if (qpol_filename_trans_get_target_type(q, filename_trans, &type))
|
|
goto err;
|
|
|
|
if (qpol_type_get_name(q, type, &tmp_name))
|
|
goto err;
|
|
|
|
if (py_insert_string(dict, "target", tmp_name))
|
|
goto err;
|
|
|
|
if (qpol_filename_trans_get_object_class(q, filename_trans, &obj_class))
|
|
goto err;
|
|
|
|
if (qpol_class_get_name(q, obj_class, &tmp_name))
|
|
goto err;
|
|
|
|
if (py_insert_string(dict, "class", tmp_name))
|
|
goto err;
|
|
|
|
if (qpol_filename_trans_get_default_type(q, filename_trans, &type))
|
|
goto err;
|
|
if (qpol_type_get_name(q, type, &tmp_name))
|
|
goto err;
|
|
if (py_insert_string(dict, "transtype", tmp_name))
|
|
goto err;
|
|
|
|
if (! qpol_filename_trans_get_filename(q, filename_trans, &tmp_name)) {
|
|
if (py_insert_string(dict, "filename", tmp_name))
|
|
goto err;
|
|
}
|
|
|
|
rt = py_append_obj(list, dict);
|
|
dict = NULL;
|
|
if (rt) goto err;
|
|
|
|
free(filename_trans_str); filename_trans_str = NULL;
|
|
free(expr); expr = NULL;
|
|
}
|
|
goto cleanup;
|
|
|
|
err:
|
|
error = errno;
|
|
PyErr_SetString(PyExc_RuntimeError,strerror(errno));
|
|
py_decref(dict);
|
|
cleanup:
|
|
free(tmp);
|
|
free(filename_trans_str);
|
|
free(expr);
|
|
errno = error;
|
|
return list;
|
|
}
|
|
|
|
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) // Add this regardless of policy capabilities
|
|
rules |= QPOL_RULE_NEVERALLOW;
|
|
if (opt->auditallow || opt->all)
|
|
rules |= QPOL_RULE_AUDITALLOW;
|
|
if (opt->dontaudit || opt->all)
|
|
rules |= QPOL_RULE_DONTAUDIT;
|
|
if (rules != 0) // Setting rules = 0 means you want all the rules
|
|
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)) {
|
|
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)) {
|
|
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)) {
|
|
goto err;
|
|
}
|
|
if ((s = strdup(tok)) == NULL || apol_vector_append(opt->perm_vector, s) < 0) {
|
|
goto err;
|
|
}
|
|
s = NULL;
|
|
}
|
|
free(tmp);
|
|
tmp = NULL;
|
|
}
|
|
|
|
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)) {
|
|
goto err;
|
|
}
|
|
} else {
|
|
if (apol_avrule_get_by_query(policy, avq, v)) {
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
apol_avrule_query_destroy(&avq);
|
|
return 0;
|
|
|
|
err:
|
|
error = errno;
|
|
PyErr_SetString(PyExc_RuntimeError,strerror(error));
|
|
apol_vector_destroy(v);
|
|
apol_avrule_query_destroy(&avq);
|
|
free(tmp);
|
|
free(s);
|
|
errno = error;
|
|
return -1;
|
|
}
|
|
|
|
static PyObject* get_av_results(const apol_policy_t * policy, const apol_vector_t * v, PyObject *output)
|
|
{
|
|
PyObject *obj, *dict=NULL;
|
|
PyObject *permlist = NULL;
|
|
PyObject *boollist = NULL;
|
|
uint32_t rule_type = 0;
|
|
int rt;
|
|
int error = 0;
|
|
qpol_policy_t *q;
|
|
size_t i, num_rules = 0;
|
|
const qpol_avrule_t *rule = NULL;
|
|
char *tmp = NULL, *rule_str = NULL;
|
|
qpol_cond_expr_node_t *expr = NULL;
|
|
qpol_iterator_t *iter = NULL;
|
|
const qpol_cond_t *cond = NULL;
|
|
uint32_t enabled = 0;
|
|
const qpol_type_t *type;
|
|
const char *tmp_name;
|
|
const qpol_class_t *obj_class = NULL;
|
|
|
|
if (!policy || !v) {
|
|
errno = EINVAL;
|
|
goto err;
|
|
}
|
|
|
|
if (!(num_rules = apol_vector_get_size(v)))
|
|
return NULL;
|
|
|
|
q = apol_policy_get_qpol(policy);
|
|
|
|
for (i = 0; i < num_rules; i++) {
|
|
if (!(rule = apol_vector_get_element(v, i)))
|
|
goto err;
|
|
|
|
dict = PyDict_New();
|
|
if (!dict) goto err;
|
|
|
|
if (qpol_avrule_get_rule_type(q, rule, &rule_type))
|
|
goto err;
|
|
|
|
if (!(tmp_name = apol_rule_type_to_str(rule_type))) {
|
|
PyErr_SetString(PyExc_RuntimeError, "Could not get TE rule type's string");
|
|
errno = EINVAL;
|
|
goto err;
|
|
}
|
|
|
|
if (py_insert_string(dict, "type", tmp_name))
|
|
goto err;
|
|
|
|
if (qpol_avrule_get_source_type(q, rule, &type)) {
|
|
goto err;
|
|
}
|
|
|
|
if (qpol_type_get_name(q, type, &tmp_name)) {
|
|
goto err;
|
|
}
|
|
|
|
if (py_insert_string(dict, "source", tmp_name))
|
|
goto err;
|
|
|
|
if (qpol_avrule_get_target_type(q, rule, &type)) {
|
|
goto err;
|
|
}
|
|
if (qpol_type_get_name(q, type, &tmp_name)) {
|
|
goto err;
|
|
}
|
|
|
|
if (py_insert_string(dict, "target", tmp_name))
|
|
goto err;
|
|
|
|
if (qpol_avrule_get_object_class(q, rule, &obj_class)) {
|
|
goto err;
|
|
}
|
|
if (qpol_class_get_name(q, obj_class, &tmp_name)) {
|
|
goto err;
|
|
}
|
|
|
|
if (py_insert_string(dict, "class", tmp_name))
|
|
goto err;
|
|
|
|
if (qpol_avrule_get_perm_iter(q, rule, &iter)) {
|
|
goto err;
|
|
}
|
|
|
|
permlist = PyList_New(0);
|
|
if (! permlist) goto err;
|
|
|
|
for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
|
|
const char *perm_name = NULL;
|
|
if (qpol_iterator_get_item(iter, (void **)&perm_name))
|
|
goto err;
|
|
if (py_append_string(permlist, perm_name))
|
|
goto err;
|
|
}
|
|
|
|
rt = PyDict_SetItemString(dict, "permlist", permlist);
|
|
py_decref(permlist); permlist=NULL;
|
|
if (rt) goto err;
|
|
|
|
if (qpol_avrule_get_cond(q, rule, &cond))
|
|
goto err;
|
|
if (qpol_avrule_get_is_enabled(q, rule, &enabled))
|
|
goto err;
|
|
|
|
obj = PyBool_FromLong(enabled);
|
|
rt = PyDict_SetItemString(dict, "enabled", obj);
|
|
py_decref(obj);
|
|
|
|
if (cond) {
|
|
obj = get_bool(q, cond, enabled);
|
|
if (!obj) goto err;
|
|
rt = PyDict_SetItemString(dict, "boolean", obj);
|
|
py_decref(obj);
|
|
}
|
|
|
|
rt = py_append_obj(output, dict);
|
|
py_decref(dict); dict=NULL;
|
|
if (rt) goto err;
|
|
|
|
free(rule_str); rule_str = NULL;
|
|
free(expr); expr = NULL;
|
|
}
|
|
goto cleanup;
|
|
|
|
err:
|
|
error = errno;
|
|
PyErr_SetString(PyExc_RuntimeError,strerror(errno));
|
|
py_decref(dict);
|
|
py_decref(permlist);
|
|
py_decref(boollist);
|
|
|
|
cleanup:
|
|
free(tmp);
|
|
free(rule_str);
|
|
free(expr);
|
|
errno = error;
|
|
return output;
|
|
}
|
|
|
|
PyObject* search(bool allow,
|
|
bool neverallow,
|
|
bool auditallow,
|
|
bool dontaudit,
|
|
bool transition,
|
|
bool role_allow,
|
|
const char *src_name,
|
|
const char *tgt_name,
|
|
const char *class_name,
|
|
const char *permlist
|
|
)
|
|
{
|
|
options_t cmd_opts;
|
|
PyObject *output = NULL;
|
|
apol_vector_t *v = NULL;
|
|
|
|
memset(&cmd_opts, 0, sizeof(cmd_opts));
|
|
cmd_opts.indirect = true;
|
|
cmd_opts.show_cond = true;
|
|
cmd_opts.allow = allow;
|
|
cmd_opts.nallow = neverallow;
|
|
cmd_opts.auditallow = auditallow;
|
|
cmd_opts.dontaudit = dontaudit;
|
|
cmd_opts.type = transition;
|
|
cmd_opts.role_allow = role_allow;
|
|
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);
|
|
}
|
|
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))) {
|
|
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;
|
|
}
|
|
output = PyList_New(0);
|
|
if (!output)
|
|
goto cleanup;
|
|
|
|
if (v) {
|
|
get_av_results(policy, v, output);
|
|
}
|
|
|
|
apol_vector_destroy(&v);
|
|
if (perform_te_query(policy, &cmd_opts, &v)) {
|
|
goto cleanup;
|
|
}
|
|
if (v) {
|
|
get_te_results(policy, v, output);
|
|
}
|
|
|
|
if (cmd_opts.all || cmd_opts.type) {
|
|
apol_vector_destroy(&v);
|
|
if (perform_ft_query(policy, &cmd_opts, &v)) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (v) {
|
|
get_ft_results(policy, v, output);
|
|
}
|
|
}
|
|
|
|
if (cmd_opts.all || cmd_opts.role_allow) {
|
|
apol_vector_destroy(&v);
|
|
if (perform_ra_query(policy, &cmd_opts, &v)) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (v) {
|
|
get_ra_results(policy, v, output);
|
|
}
|
|
}
|
|
|
|
apol_vector_destroy(&v);
|
|
|
|
cleanup:
|
|
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);
|
|
|
|
if (output && PyList_GET_SIZE(output) == 0) {
|
|
py_decref(output);
|
|
return Py_None;
|
|
}
|
|
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_search(PyObject *UNUSED(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");
|
|
int transition = Dict_ContainsInt(dict, "transition");
|
|
int role_allow = Dict_ContainsInt(dict, "role_allow");
|
|
|
|
if (!policy) {
|
|
PyErr_SetString(PyExc_RuntimeError,"Policy not loaded");
|
|
return NULL;
|
|
}
|
|
const char *src_name = Dict_ContainsString(dict, "source");
|
|
const char *tgt_name = Dict_ContainsString(dict, "target");
|
|
const char *class_name = Dict_ContainsString(dict, "class");
|
|
const char *permlist = Dict_ContainsString(dict, "permlist");
|
|
|
|
return search(allow, neverallow, auditallow, dontaudit, transition, role_allow, src_name, tgt_name, class_name, permlist);
|
|
}
|