summaryrefslogtreecommitdiffstats
path: root/libapol/src/policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'libapol/src/policy.c')
-rw-r--r--libapol/src/policy.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/libapol/src/policy.c b/libapol/src/policy.c
new file mode 100644
index 0000000..95ab7cd
--- /dev/null
+++ b/libapol/src/policy.c
@@ -0,0 +1,217 @@
+/**
+ * @file
+ *
+ * Public interface for SELinux policies.
+ *
+ * @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 "policy-query-internal.h"
+
+#include <apol/perm-map.h>
+#include <apol/domain-trans-analysis.h>
+
+#include <qpol/policy.h>
+#include <qpol/policy_extend.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void apol_handle_default_callback(void *varg __attribute__ ((unused)), const apol_policy_t * p
+ __attribute__ ((unused)), int level, const char *fmt, va_list va_args)
+{
+ switch (level) {
+ case APOL_MSG_INFO:
+ {
+ /* by default do not display these messages */
+ return;
+ }
+ case APOL_MSG_WARN:
+ {
+ fprintf(stderr, "WARNING: ");
+ break;
+ }
+ case APOL_MSG_ERR:
+ default:
+ {
+ fprintf(stderr, "ERROR: ");
+ break;
+ }
+ }
+ vfprintf(stderr, fmt, va_args);
+ fprintf(stderr, "\n");
+}
+
+static void qpol_handle_route_to_callback(void *varg, const qpol_policy_t * policy
+ __attribute__ ((unused)), int level, const char *fmt, va_list ap)
+{
+ apol_policy_t *p = (apol_policy_t *) varg;
+ if (p == NULL) {
+ apol_handle_default_callback(NULL, NULL, level, fmt, ap);
+ } else if (p->msg_callback != NULL) {
+ p->msg_callback(p->msg_callback_arg, p, level, fmt, ap);
+ }
+}
+
+apol_policy_t *apol_policy_create_from_policy_path(const apol_policy_path_t * path, const int options,
+ apol_callback_fn_t msg_callback, void *varg)
+{
+ apol_policy_t *policy;
+ const char *primary_path;
+ int policy_type;
+ if (!path) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (!(policy = calloc(1, sizeof(apol_policy_t)))) {
+ ERR(NULL, "%s", strerror(ENOMEM));
+ return NULL; /* errno set by calloc */
+ }
+ if (msg_callback != NULL) {
+ policy->msg_callback = msg_callback;
+ } else {
+ policy->msg_callback = apol_handle_default_callback;
+ }
+ policy->msg_callback_arg = varg;
+ primary_path = apol_policy_path_get_primary(path);
+ INFO(policy, "Loading policy %s.", primary_path);
+ policy_type = qpol_policy_open_from_file(primary_path, &policy->p, qpol_handle_route_to_callback, policy, options);
+ if (policy_type < 0) {
+ ERR(policy, "Unable to open policy %s.", primary_path);
+ apol_policy_destroy(&policy);
+ return NULL; /* qpol sets errno */
+ }
+ policy->policy_type = policy_type;
+
+ if (apol_policy_path_get_type(path) == APOL_POLICY_PATH_TYPE_MODULAR) {
+ if (!qpol_policy_has_capability(policy->p, QPOL_CAP_MODULES)) {
+ INFO(policy, "%s is not a base policy.", primary_path);
+ return policy;
+ }
+ const apol_vector_t *modules = apol_policy_path_get_modules(path);
+ size_t i;
+ for (i = 0; i < apol_vector_get_size(modules); i++) {
+ const char *module_path = apol_vector_get_element(modules, i);
+ qpol_module_t *mod = NULL;
+ INFO(policy, "Loading module %s.", module_path);
+ if (qpol_module_create_from_file(module_path, &mod)) {
+ ERR(policy, "Error loading module %s.", module_path);
+ apol_policy_destroy(&policy);
+ return NULL;
+ }
+ if (qpol_policy_append_module(policy->p, mod)) {
+ ERR(policy, "Error loading module %s.", module_path);
+ apol_policy_destroy(&policy);
+ qpol_module_destroy(&mod);
+ return NULL;
+ }
+ }
+ INFO(policy, "%s", "Linking modules into base policy.");
+ if (qpol_policy_rebuild(policy->p, options)) {
+ apol_policy_destroy(&policy);
+ return NULL;
+ }
+ }
+ return policy;
+}
+
+void apol_policy_destroy(apol_policy_t ** policy)
+{
+ if (policy != NULL && *policy != NULL) {
+ qpol_policy_destroy(&((*policy)->p));
+ permmap_destroy(&(*policy)->pmap);
+ domain_trans_table_destroy(&(*policy)->domain_trans_table);
+ free(*policy);
+ *policy = NULL;
+ }
+}
+
+int apol_policy_get_policy_type(const apol_policy_t * policy)
+{
+ if (policy == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ return policy->policy_type;
+}
+
+qpol_policy_t *apol_policy_get_qpol(const apol_policy_t * policy)
+{
+ if (policy == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ return policy->p;
+}
+
+int apol_policy_is_mls(const apol_policy_t * p)
+{
+ if (p == NULL) {
+ return -1;
+ }
+ return qpol_policy_has_capability(p->p, QPOL_CAP_MLS);
+}
+
+char *apol_policy_get_version_type_mls_str(const apol_policy_t * p)
+{
+ unsigned int version;
+ char *policy_type, *mls, buf[64];
+ if (qpol_policy_get_policy_version(p->p, &version) < 0) {
+ return NULL;
+ }
+ switch (p->policy_type) {
+ case QPOL_POLICY_KERNEL_SOURCE:
+ policy_type = "source";
+ break;
+ case QPOL_POLICY_KERNEL_BINARY:
+ policy_type = "binary";
+ break;
+ case QPOL_POLICY_MODULE_BINARY:
+ policy_type = "modular";
+ break;
+ default:
+ policy_type = "unknown";
+ break;
+ }
+ if (qpol_policy_has_capability(p->p, QPOL_CAP_MLS)) {
+ mls = "mls";
+ } else {
+ mls = "non-mls";
+ }
+ if (snprintf(buf, sizeof(buf), "v.%u (%s, %s)", version, policy_type, mls) == -1) {
+ return NULL;
+ }
+ return strdup(buf);
+}
+
+void apol_handle_msg(const apol_policy_t * p, int level, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (p == NULL) {
+ apol_handle_default_callback(NULL, NULL, level, fmt, ap);
+ } else if (p->msg_callback != NULL) {
+ p->msg_callback(p->msg_callback_arg, p, level, fmt, ap);
+ }
+ va_end(ap);
+}