summaryrefslogtreecommitdiffstats
path: root/libqpol/src/syn_rule_query.c
diff options
context:
space:
mode:
Diffstat (limited to 'libqpol/src/syn_rule_query.c')
-rw-r--r--libqpol/src/syn_rule_query.c782
1 files changed, 782 insertions, 0 deletions
diff --git a/libqpol/src/syn_rule_query.c b/libqpol/src/syn_rule_query.c
new file mode 100644
index 0000000..3e63204
--- /dev/null
+++ b/libqpol/src/syn_rule_query.c
@@ -0,0 +1,782 @@
+/**
+ * @file
+ * Public interface for querying syntactic rules from the extended
+ * policy image.
+ *
+ * @author Jeremy A. Mowery jmowery@tresys.com
+ * @author Jason Tang jtang@tresys.com
+ *
+ * Copyright (C) 2006-2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include <qpol/syn_rule_query.h>
+#include <sepol/policydb/policydb.h>
+#include <sepol/policydb/util.h>
+#include <sepol/policydb/conditional.h>
+#include "qpol_internal.h"
+#include "iterator_internal.h"
+#include "syn_rule_internal.h"
+#include <errno.h>
+#include <stdlib.h>
+
+typedef struct syn_rule_class_state
+{
+ class_perm_node_t *head;
+ class_perm_node_t *cur;
+} syn_rule_class_state_t;
+
+static int syn_rule_class_state_end(const qpol_iterator_t * iter)
+{
+ syn_rule_class_state_t *srcs = NULL;
+
+ if (!iter || !(srcs = (syn_rule_class_state_t *) qpol_iterator_state(iter))) {
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ if (srcs->cur == NULL)
+ return 1;
+ else
+ return 0;
+}
+
+static void *syn_rule_class_state_get_cur(const qpol_iterator_t * iter)
+{
+ syn_rule_class_state_t *srcs = NULL;
+ const policydb_t *db = NULL;
+
+ if (!iter || !(srcs = (syn_rule_class_state_t *) qpol_iterator_state(iter)) ||
+ !(db = qpol_iterator_policy(iter)) || qpol_iterator_end(iter)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ return db->class_val_to_struct[srcs->cur->class - 1];
+}
+
+static int syn_rule_class_state_next(qpol_iterator_t * iter)
+{
+ syn_rule_class_state_t *srcs = NULL;
+
+ if (!iter || !(srcs = (syn_rule_class_state_t *) qpol_iterator_state(iter))) {
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+ if (qpol_iterator_end(iter)) {
+ errno = ERANGE;
+ return STATUS_ERR;
+ }
+
+ srcs->cur = srcs->cur->next;
+
+ return STATUS_SUCCESS;
+}
+
+static size_t syn_rule_class_state_size(const qpol_iterator_t * iter)
+{
+ syn_rule_class_state_t *srcs = NULL;
+ size_t count = 0;
+ class_perm_node_t *cpn = NULL;
+
+ if (!iter || !(srcs = (syn_rule_class_state_t *) qpol_iterator_state(iter))) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ for (cpn = srcs->head; cpn; cpn = cpn->next)
+ count++;
+
+ return count;
+}
+
+typedef struct syn_rule_perm_state
+{
+ char **perm_list;
+ size_t perm_list_sz;
+ size_t cur;
+} syn_rule_perm_state_t;
+
+static int syn_rule_perm_state_end(const qpol_iterator_t * iter)
+{
+ syn_rule_perm_state_t *srps = NULL;
+
+ if (!iter || !(srps = (syn_rule_perm_state_t *) qpol_iterator_state(iter))) {
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ return (srps->cur >= srps->perm_list_sz ? 1 : 0);
+}
+
+static void *syn_rule_perm_state_get_cur(const qpol_iterator_t * iter)
+{
+ syn_rule_perm_state_t *srps = NULL;
+
+ if (!iter || !(srps = (syn_rule_perm_state_t *) qpol_iterator_state(iter)) || qpol_iterator_end(iter)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ return srps->perm_list[srps->cur];
+}
+
+static int syn_rule_perm_state_next(qpol_iterator_t * iter)
+{
+ syn_rule_perm_state_t *srps = NULL;
+
+ if (!iter || !(srps = (syn_rule_perm_state_t *) qpol_iterator_state(iter))) {
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+ if (qpol_iterator_end(iter)) {
+ errno = ERANGE;
+ return STATUS_ERR;
+ }
+
+ srps->cur++;
+
+ return STATUS_SUCCESS;
+}
+
+static size_t syn_rule_perm_state_size(const qpol_iterator_t * iter)
+{
+ syn_rule_perm_state_t *srps = NULL;
+
+ if (!iter || !(srps = (syn_rule_perm_state_t *) qpol_iterator_state(iter))) {
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ return srps->perm_list_sz;
+}
+
+static void syn_rule_perm_state_free(void *state)
+{
+ size_t i;
+
+ syn_rule_perm_state_t *srps = (syn_rule_perm_state_t *) state;
+
+ if (!srps)
+ return;
+
+ for (i = 0; i < srps->perm_list_sz; i++)
+ free(srps->perm_list[i]);
+ free(srps->perm_list);
+ free(srps);
+}
+
+/***************************** type set functions ****************************/
+
+int qpol_type_set_get_included_types_iter(const qpol_policy_t * policy, const qpol_type_set_t * ts, qpol_iterator_t ** iter)
+{
+ type_set_t *internal_ts = NULL;
+ ebitmap_state_t *es = NULL;
+ int error = 0;
+
+ if (iter)
+ *iter = NULL;
+
+ if (!policy || !ts || !iter) {
+ ERR(policy, "%s", strerror(EINVAL));
+ error = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_ts = (type_set_t *) ts;
+
+ es = calloc(1, sizeof(ebitmap_state_t));
+ if (!es) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ errno = error;
+ return STATUS_ERR;
+ }
+
+ es->bmap = &(internal_ts->types);
+ es->cur = es->bmap->node ? es->bmap->node->startbit : 0;
+
+ if (qpol_iterator_create(policy, es, ebitmap_state_get_cur_type,
+ ebitmap_state_next, ebitmap_state_end, ebitmap_state_size, free, iter)) {
+ free(es);
+ return STATUS_ERR;
+ }
+
+ if (es->bmap->node && !ebitmap_get_bit(es->bmap, es->cur))
+ ebitmap_state_next(*iter);
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_type_set_get_subtracted_types_iter(const qpol_policy_t * policy, const qpol_type_set_t * ts, qpol_iterator_t ** iter)
+{
+ type_set_t *internal_ts = NULL;
+ ebitmap_state_t *es = NULL;
+ int error = 0;
+
+ if (iter)
+ *iter = NULL;
+
+ if (!policy || !ts || !iter) {
+ ERR(policy, "%s", strerror(EINVAL));
+ error = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_ts = (type_set_t *) ts;
+
+ es = calloc(1, sizeof(ebitmap_state_t));
+ if (!es) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ errno = error;
+ return STATUS_ERR;
+ }
+
+ es->bmap = &(internal_ts->negset);
+ es->cur = es->bmap->node ? es->bmap->node->startbit : 0;
+
+ if (qpol_iterator_create(policy, es, ebitmap_state_get_cur_type,
+ ebitmap_state_next, ebitmap_state_end, ebitmap_state_size, free, iter)) {
+ free(es);
+ return STATUS_ERR;
+ }
+
+ if (es->bmap->node && !ebitmap_get_bit(es->bmap, es->cur))
+ ebitmap_state_next(*iter);
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_type_set_get_is_star(const qpol_policy_t * policy, const qpol_type_set_t * ts, uint32_t * is_star)
+{
+ type_set_t *internal_ts = NULL;
+
+ if (is_star)
+ *is_star = 0;
+
+ if (!policy || !ts || !is_star) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_ts = (type_set_t *) ts;
+
+ if (internal_ts->flags == TYPE_STAR)
+ *is_star = 1;
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_type_set_get_is_comp(const qpol_policy_t * policy, const qpol_type_set_t * ts, uint32_t * is_comp)
+{
+ type_set_t *internal_ts = NULL;
+
+ if (is_comp)
+ *is_comp = 0;
+
+ if (!policy || !ts || !is_comp) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_ts = (type_set_t *) ts;
+
+ if (internal_ts->flags == TYPE_COMP)
+ *is_comp = 1;
+
+ return STATUS_SUCCESS;
+}
+
+/***************************** syn_avule functions ****************************/
+
+int qpol_syn_avrule_get_rule_type(const qpol_policy_t * policy, const qpol_syn_avrule_t * rule, uint32_t * rule_type)
+{
+ avrule_t *internal_rule = NULL;
+
+ if (rule_type)
+ *rule_type = 0;
+
+ if (!policy || !rule || !rule_type) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_rule = ((struct qpol_syn_rule *)rule)->rule;
+
+ if (internal_rule->specified == AVRULE_DONTAUDIT)
+ *rule_type = QPOL_RULE_DONTAUDIT;
+ else
+ *rule_type = internal_rule->specified;
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_avrule_get_source_type_set(const qpol_policy_t * policy, const qpol_syn_avrule_t * rule,
+ const qpol_type_set_t ** source_set)
+{
+ avrule_t *internal_rule = NULL;
+
+ if (source_set)
+ *source_set = NULL;
+
+ if (!policy || !rule || !source_set) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_rule = ((struct qpol_syn_rule *)rule)->rule;
+
+ *source_set = (qpol_type_set_t *) (&internal_rule->stypes);
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_avrule_get_target_type_set(const qpol_policy_t * policy, const qpol_syn_avrule_t * rule,
+ const qpol_type_set_t ** target_set)
+{
+ avrule_t *internal_rule = NULL;
+
+ if (target_set)
+ *target_set = NULL;
+
+ if (!policy || !rule || !target_set) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_rule = ((struct qpol_syn_rule *)rule)->rule;
+
+ *target_set = (qpol_type_set_t *) (&internal_rule->ttypes);
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_avrule_get_is_target_self(const qpol_policy_t * policy, const qpol_syn_avrule_t * rule, uint32_t * is_self)
+{
+ avrule_t *internal_rule = NULL;
+
+ if (is_self)
+ *is_self = 0;
+
+ if (!policy || !rule || !is_self) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_rule = ((struct qpol_syn_rule *)rule)->rule;
+
+ if (internal_rule->flags & RULE_SELF)
+ *is_self = 1;
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_avrule_get_class_iter(const qpol_policy_t * policy, const qpol_syn_avrule_t * rule, qpol_iterator_t ** classes)
+{
+ syn_rule_class_state_t *srcs = NULL;
+ avrule_t *internal_rule = NULL;
+ int error = 0;
+
+ if (classes)
+ *classes = NULL;
+
+ if (!policy || !rule || !classes) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ if (!(srcs = calloc(1, sizeof(syn_rule_class_state_t)))) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ errno = error;
+ return STATUS_ERR;
+ }
+
+ internal_rule = ((struct qpol_syn_rule *)rule)->rule;
+ srcs->head = srcs->cur = internal_rule->perms;
+
+ if (qpol_iterator_create(policy, (void *)srcs,
+ syn_rule_class_state_get_cur, syn_rule_class_state_next,
+ syn_rule_class_state_end, syn_rule_class_state_size, free, classes)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ free(srcs);
+ errno = error;
+ return STATUS_ERR;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_avrule_get_perm_iter(const qpol_policy_t * policy, const qpol_syn_avrule_t * rule, qpol_iterator_t ** perms)
+{
+ avrule_t *internal_rule = NULL;
+ policydb_t *db = NULL;
+ char **perm_list, *tmp = NULL, **tmp_copy = NULL;
+ class_perm_node_t *node = NULL;
+ size_t node_num = 0, i, cur, perm_list_sz = 0;
+ int error = 0;
+ syn_rule_perm_state_t *srps = NULL;
+
+ if (perms)
+ *perms = NULL;
+
+ if (!policy || !rule || !perms) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ db = &policy->p->p;
+ internal_rule = ((struct qpol_syn_rule *)rule)->rule;
+ for (node = internal_rule->perms; node; node = node->next)
+ node_num++;
+
+ /* for now allocate space for maximum number of unique perms */
+ perm_list = calloc(node_num * 32, sizeof(char *));
+ if (!perm_list) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ errno = error;
+ return STATUS_ERR;
+ }
+
+ for (node = internal_rule->perms; node; node = node->next) {
+ for (i = 0; i < db->class_val_to_struct[node->class - 1]->permissions.nprim; i++) {
+ if (!(node->data & (1 << i)))
+ continue;
+ tmp = sepol_av_to_string(db, node->class, (sepol_access_vector_t) (1 << i));
+ if (tmp) {
+ tmp++; /* remove prepended space */
+ for (cur = 0; cur < perm_list_sz; cur++)
+ if (!strcmp(tmp, perm_list[cur]))
+ break;
+ if (cur < perm_list_sz)
+ continue;
+ perm_list[perm_list_sz] = strdup(tmp);
+ if (!(perm_list[perm_list_sz])) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto err;
+ }
+ perm_list_sz++;
+ } else {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto err;
+ }
+ }
+ }
+
+ /* shrink to actual needed size */
+ tmp_copy = realloc(perm_list, perm_list_sz * sizeof(char *));
+ if (!tmp_copy) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto err;
+ }
+ perm_list = tmp_copy;
+
+ srps = calloc(1, sizeof(syn_rule_perm_state_t));
+ if (!srps) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto err;
+ }
+ srps->perm_list = perm_list;
+ srps->perm_list_sz = perm_list_sz;
+ srps->cur = 0;
+
+ if (qpol_iterator_create(policy, (void *)srps,
+ syn_rule_perm_state_get_cur, syn_rule_perm_state_next,
+ syn_rule_perm_state_end, syn_rule_perm_state_size, syn_rule_perm_state_free, perms)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto err;
+ }
+
+ return STATUS_SUCCESS;
+
+ err:
+ for (i = 0; i < perm_list_sz; i++)
+ free(perm_list[i]);
+ free(perm_list);
+ errno = error;
+ return STATUS_ERR;
+}
+
+int qpol_syn_avrule_get_lineno(const qpol_policy_t * policy, const qpol_syn_avrule_t * rule, unsigned long *lineno)
+{
+ avrule_t *internal_rule = NULL;
+
+ if (lineno)
+ *lineno = 0;
+
+ if (!policy || !rule || !lineno) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_rule = ((struct qpol_syn_rule *)rule)->rule;
+
+ *lineno = internal_rule->line;
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_avrule_get_cond(const qpol_policy_t * policy, const qpol_syn_avrule_t * rule, const qpol_cond_t ** cond)
+{
+ if (cond)
+ *cond = NULL;
+
+ if (!policy || !rule || !cond) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ *cond = (qpol_cond_t *) ((struct qpol_syn_rule *)rule)->cond;
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_avrule_get_is_enabled(const qpol_policy_t * policy, const qpol_syn_avrule_t * rule, uint32_t * is_enabled)
+{
+ int truth;
+ if (is_enabled)
+ *is_enabled = 0;
+
+ if (!policy || !rule || !is_enabled) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ if (!((struct qpol_syn_rule *)rule)->cond)
+ *is_enabled = 1;
+ else {
+ truth = cond_evaluate_expr(&policy->p->p, ((struct qpol_syn_rule *)rule)->cond->expr);
+ if (truth < 0) {
+ ERR(policy, "%s", strerror(ERANGE));
+ errno = ERANGE;
+ return STATUS_ERR;
+ }
+ if (!((struct qpol_syn_rule *)rule)->cond_branch)
+ *is_enabled = truth;
+ else
+ *is_enabled = truth ? 0 : 1;
+ }
+ return STATUS_SUCCESS;
+}
+
+/***************************** syn_terule functions ****************************/
+
+int qpol_syn_terule_get_rule_type(const qpol_policy_t * policy, const qpol_syn_terule_t * rule, uint32_t * rule_type)
+{
+ avrule_t *internal_rule = NULL;
+
+ if (rule_type)
+ *rule_type = 0;
+
+ if (!policy || !rule || !rule_type) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_rule = ((struct qpol_syn_rule *)rule)->rule;
+
+ *rule_type = internal_rule->specified;
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_terule_get_source_type_set(const qpol_policy_t * policy, const qpol_syn_terule_t * rule,
+ const qpol_type_set_t ** source_set)
+{
+ avrule_t *internal_rule = NULL;
+
+ if (source_set)
+ *source_set = NULL;
+
+ if (!policy || !rule || !source_set) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_rule = ((struct qpol_syn_rule *)rule)->rule;
+
+ *source_set = (qpol_type_set_t *) (&internal_rule->stypes);
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_terule_get_target_type_set(const qpol_policy_t * policy, const qpol_syn_terule_t * rule,
+ const qpol_type_set_t ** target_set)
+{
+ avrule_t *internal_rule = NULL;
+
+ if (target_set)
+ *target_set = NULL;
+
+ if (!policy || !rule || !target_set) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_rule = ((struct qpol_syn_rule *)rule)->rule;
+
+ *target_set = (qpol_type_set_t *) (&internal_rule->ttypes);
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_terule_get_class_iter(const qpol_policy_t * policy, const qpol_syn_terule_t * rule, qpol_iterator_t ** classes)
+{
+ syn_rule_class_state_t *srcs = NULL;
+ avrule_t *internal_rule = NULL;
+ int error = 0;
+
+ if (classes)
+ *classes = NULL;
+
+ if (!policy || !rule || !classes) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ if (!(srcs = calloc(1, sizeof(syn_rule_class_state_t)))) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ errno = error;
+ return STATUS_ERR;
+ }
+
+ internal_rule = ((struct qpol_syn_rule *)rule)->rule;
+ srcs->head = srcs->cur = internal_rule->perms;
+
+ if (qpol_iterator_create(policy, (void *)srcs,
+ syn_rule_class_state_get_cur, syn_rule_class_state_next,
+ syn_rule_class_state_end, syn_rule_class_state_size, free, classes)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ free(srcs);
+ errno = error;
+ return STATUS_ERR;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_terule_get_default_type(const qpol_policy_t * policy, const qpol_syn_terule_t * rule, const qpol_type_t ** dflt)
+{
+ avrule_t *internal_rule = NULL;
+ policydb_t *db = NULL;
+
+ if (dflt)
+ *dflt = 0;
+
+ if (!policy || !rule || !dflt) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_rule = ((struct qpol_syn_rule *)rule)->rule;
+ db = &policy->p->p;
+
+ /* since it is required that default be the same for all classes just return the first */
+ *dflt = (qpol_type_t *) (db->type_val_to_struct[internal_rule->perms->data - 1]);
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_terule_get_lineno(const qpol_policy_t * policy, const qpol_syn_terule_t * rule, unsigned long *lineno)
+{
+ avrule_t *internal_rule = NULL;
+
+ if (lineno)
+ *lineno = 0;
+
+ if (!policy || !rule || !lineno) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ internal_rule = ((struct qpol_syn_rule *)rule)->rule;
+
+ *lineno = internal_rule->line;
+
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_terule_get_cond(const qpol_policy_t * policy, const qpol_syn_terule_t * rule, const qpol_cond_t ** cond)
+{
+ if (cond)
+ *cond = NULL;
+
+ if (!policy || !rule || !cond) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ *cond = (qpol_cond_t *) ((struct qpol_syn_rule *)rule)->cond;
+ return STATUS_SUCCESS;
+}
+
+int qpol_syn_terule_get_is_enabled(const qpol_policy_t * policy, const qpol_syn_terule_t * rule, uint32_t * is_enabled)
+{
+ int truth;
+ if (is_enabled)
+ *is_enabled = 0;
+
+ if (!policy || !rule || !is_enabled) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return STATUS_ERR;
+ }
+
+ if (!((struct qpol_syn_rule *)rule)->cond)
+ *is_enabled = 1;
+ else {
+ truth = cond_evaluate_expr(&policy->p->p, ((struct qpol_syn_rule *)rule)->cond->expr);
+ if (truth < 0) {
+ ERR(policy, "%s", strerror(ERANGE));
+ errno = ERANGE;
+ return STATUS_ERR;
+ }
+ if (!((struct qpol_syn_rule *)rule)->cond_branch)
+ *is_enabled = truth;
+ else
+ *is_enabled = truth ? 0 : 1;
+ }
+ return STATUS_SUCCESS;
+}