summaryrefslogtreecommitdiffstats
path: root/libapol/src/policy-path.c
diff options
context:
space:
mode:
Diffstat (limited to 'libapol/src/policy-path.c')
-rw-r--r--libapol/src/policy-path.c409
1 files changed, 409 insertions, 0 deletions
diff --git a/libapol/src/policy-path.c b/libapol/src/policy-path.c
new file mode 100644
index 0000000..3633ebd
--- /dev/null
+++ b/libapol/src/policy-path.c
@@ -0,0 +1,409 @@
+/**
+ * @file
+ *
+ * Implementation of policy path object.
+ *
+ * @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 <apol/policy-path.h>
+#include <apol/util.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+static const char *POLICY_PATH_MAGIC = "policy_list";
+static const int POLICY_PATH_MAX_VERSION = 1;
+
+struct apol_policy_path
+{
+ apol_policy_path_type_e path_type;
+ char *base;
+ apol_vector_t *modules;
+};
+
+apol_policy_path_t *apol_policy_path_create(apol_policy_path_type_e path_type, const char *path, const apol_vector_t * modules)
+{
+ apol_policy_path_t *p = NULL;
+
+ if (path == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if ((p = calloc(1, sizeof(*p))) == NULL) {
+ return NULL;
+ }
+ p->path_type = path_type;
+ if ((p->base = strdup(path)) == NULL) {
+ apol_policy_path_destroy(&p);
+ return NULL;
+ }
+ if (p->path_type == APOL_POLICY_PATH_TYPE_MODULAR) {
+ if (modules == NULL) {
+ p->modules = apol_vector_create(free);
+ } else {
+ p->modules = apol_vector_create_from_vector(modules, apol_str_strdup, NULL, free);
+ }
+ if (p->modules == NULL) {
+ apol_policy_path_destroy(&p);
+ return NULL;
+ }
+ apol_vector_sort_uniquify(p->modules, apol_str_strcmp, NULL);
+ }
+ return p;
+}
+
+apol_policy_path_t *apol_policy_path_create_from_policy_path(const apol_policy_path_t * path)
+{
+ apol_policy_path_t *p;
+ if (path == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ p = apol_policy_path_create(path->path_type, path->base, path->modules);
+ return p;
+}
+
+apol_policy_path_t *apol_policy_path_create_from_file(const char *filename)
+{
+ FILE *f = NULL;
+ apol_policy_path_t *path = NULL;
+ apol_policy_path_type_e path_type;
+ char *line = NULL, *s;
+ apol_vector_t *header_tokens = NULL;
+ size_t len;
+ int read_base = 0, retval = -1, error = 0;
+
+ if (filename == NULL) {
+ error = EINVAL;
+ goto cleanup;
+ }
+ if ((f = fopen(filename, "r")) == NULL) {
+ error = errno;
+ goto cleanup;
+ }
+
+ if (getline(&line, &len, f) < 0) {
+ error = EIO;
+ goto cleanup;
+ }
+ apol_str_trim(line);
+ if (strncmp(line, POLICY_PATH_MAGIC, strlen(POLICY_PATH_MAGIC)) != 0) {
+ error = EIO;
+ goto cleanup;
+ }
+
+ apol_str_trim(line);
+ if ((header_tokens = apol_str_split(line, " ")) == NULL) {
+ error = errno;
+ goto cleanup;
+ }
+ if (apol_vector_get_size(header_tokens) < 3) {
+ error = EIO;
+ goto cleanup;
+ }
+ s = apol_vector_get_element(header_tokens, 1);
+ if (atoi(s) == 0 || atoi(s) > POLICY_PATH_MAX_VERSION) {
+ error = ENOTSUP;
+ goto cleanup;
+ }
+ s = apol_vector_get_element(header_tokens, 2);
+ if (strcmp(s, "monolithic") == 0) {
+ path_type = APOL_POLICY_PATH_TYPE_MONOLITHIC;
+ } else if (strcmp(s, "modular") == 0) {
+ path_type = APOL_POLICY_PATH_TYPE_MODULAR;
+ } else {
+ error = EIO;
+ goto cleanup;
+ }
+
+ while (getline(&line, &len, f) >= 0) {
+ apol_str_trim(line);
+ if (line[0] == '#') {
+ continue;
+ }
+ if (!read_base) {
+ /* trying to parse a base policy / monolithic policy line */
+ if ((path = apol_policy_path_create(path_type, line, NULL)) == NULL) {
+ error = errno;
+ goto cleanup;
+ }
+ read_base = 1;
+ } else {
+ /* trying to parse a module line */
+ if (path_type == APOL_POLICY_PATH_TYPE_MONOLITHIC) {
+ error = EIO;
+ goto cleanup;
+ } else {
+ if ((s = strdup(line)) == NULL || apol_vector_append(path->modules, s) < 0) {
+ error = errno;
+ free(s);
+ goto cleanup;
+ }
+ }
+ }
+ }
+ if (read_base == 0) {
+ error = EIO;
+ goto cleanup;
+ }
+ retval = 0;
+ cleanup:
+ if (f != NULL) {
+ fclose(f);
+ }
+ free(line);
+ apol_vector_destroy(&header_tokens);
+ if (retval != 0) {
+ apol_policy_path_destroy(&path);
+ errno = error;
+ }
+ return path;
+}
+
+apol_policy_path_t *apol_policy_path_create_from_string(const char *path_string)
+{
+ apol_policy_path_t *p = NULL;
+ apol_vector_t *tokens = NULL;
+ apol_policy_path_type_e path_type;
+ char *s;
+ size_t i;
+ if (path_string == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if ((tokens = apol_str_split(path_string, ":")) == NULL) {
+ return NULL;
+ }
+
+ /* first token identifies the path type */
+ if (apol_vector_get_size(tokens) < 2) {
+ apol_vector_destroy(&tokens);
+ return NULL;
+ }
+ s = apol_vector_get_element(tokens, 0);
+ if (strcmp(s, "monolithic") == 0) {
+ path_type = APOL_POLICY_PATH_TYPE_MONOLITHIC;
+ } else if (strcmp(s, "modular") == 0) {
+ path_type = APOL_POLICY_PATH_TYPE_MODULAR;
+ } else {
+ apol_vector_destroy(&tokens);
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* second token identifies gives base path */
+ s = apol_vector_get_element(tokens, 1);
+ if ((p = apol_policy_path_create(path_type, s, NULL)) == NULL) {
+ apol_vector_destroy(&tokens);
+ return NULL;
+ }
+
+ if (path_type == APOL_POLICY_PATH_TYPE_MODULAR) {
+ /* remainder are module paths */
+ for (i = 2; i < apol_vector_get_size(tokens); i++) {
+ s = apol_vector_get_element(tokens, i);
+ if ((s = strdup(s)) == NULL || apol_vector_append(p->modules, s) < 0) {
+ free(s);
+ apol_vector_destroy(&tokens);
+ apol_policy_path_destroy(&p);
+ return NULL;
+ }
+ }
+ apol_vector_sort_uniquify(p->modules, apol_str_strcmp, NULL);
+ }
+ return p;
+}
+
+void apol_policy_path_destroy(apol_policy_path_t ** path)
+{
+ if (path != NULL && *path != NULL) {
+ free((*path)->base);
+ apol_vector_destroy(&(*path)->modules);
+ free(*path);
+ *path = NULL;
+ }
+}
+
+int apol_policy_path_compare(const apol_policy_path_t * a, const apol_policy_path_t * b)
+{
+ int cmp;
+ if (a == NULL || b == NULL) {
+ errno = EINVAL;
+ return 0;
+ }
+ if ((cmp = a->path_type - b->path_type) != 0) {
+ return cmp;
+ }
+ if ((cmp = strcmp(a->base, b->base)) != 0) {
+ return cmp;
+ }
+ if (a->path_type == APOL_POLICY_PATH_TYPE_MODULAR) {
+ /* only compare module vector if that field is relevant */
+ size_t i;
+ cmp = apol_vector_compare(a->modules, b->modules, apol_str_strcmp, NULL, &i);
+ if (cmp != 0) {
+ return cmp;
+ }
+ }
+ return 0;
+}
+
+apol_policy_path_type_e apol_policy_path_get_type(const apol_policy_path_t * path)
+{
+ if (path == NULL) {
+ errno = EINVAL;
+ return APOL_POLICY_PATH_TYPE_MONOLITHIC;
+ }
+ return path->path_type;
+}
+
+const char *apol_policy_path_get_primary(const apol_policy_path_t * path)
+{
+ if (path == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ return path->base;
+}
+
+const apol_vector_t *apol_policy_path_get_modules(const apol_policy_path_t * path)
+{
+ if (path == NULL || path->path_type != APOL_POLICY_PATH_TYPE_MODULAR) {
+ errno = EINVAL;
+ return NULL;
+ }
+ return path->modules;
+}
+
+int apol_policy_path_to_file(const apol_policy_path_t * path, const char *filename)
+{
+ FILE *f = NULL;
+ char *path_type;
+ size_t i;
+ int retval = -1, error = 0;
+ if (path == NULL || filename == NULL) {
+ errno = EINVAL;
+ goto cleanup;
+ }
+ if ((f = fopen(filename, "w")) == NULL) {
+ error = errno;
+ goto cleanup;
+ }
+ if (path->path_type == APOL_POLICY_PATH_TYPE_MODULAR) {
+ path_type = "modular";
+ } else {
+ path_type = "monolithic";
+ }
+ if (fprintf(f, "%s %d %s\n", POLICY_PATH_MAGIC, POLICY_PATH_MAX_VERSION, path_type) < 0) {
+ error = errno;
+ goto cleanup;
+ }
+ if (fprintf(f, "%s\n", path->base) < 0) {
+ error = errno;
+ goto cleanup;
+ }
+ if (path->path_type == APOL_POLICY_PATH_TYPE_MODULAR) {
+ for (i = 0; i < apol_vector_get_size(path->modules); i++) {
+ char *m = apol_vector_get_element(path->modules, i);
+ if (fprintf(f, "%s\n", m) < 0) {
+ error = errno;
+ goto cleanup;
+ }
+ }
+ }
+
+ retval = 0;
+ cleanup:
+ if (f != NULL) {
+ fclose(f);
+ }
+ if (retval != 0) {
+ error = errno;
+ }
+ return retval;
+}
+
+char *apol_policy_path_to_string(const apol_policy_path_t * path)
+{
+ char *path_type;
+ char *s = NULL;
+ size_t len = 0, i;
+ if (path == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if (path->path_type == APOL_POLICY_PATH_TYPE_MODULAR) {
+ path_type = "modular";
+ } else {
+ path_type = "monolithic";
+ }
+ if (apol_str_appendf(&s, &len, "%s:%s", path_type, path->base) < 0) {
+ return NULL;
+ }
+ if (path->path_type == APOL_POLICY_PATH_TYPE_MODULAR) {
+ for (i = 0; i < apol_vector_get_size(path->modules); i++) {
+ char *m = apol_vector_get_element(path->modules, i);
+ if (apol_str_appendf(&s, &len, ":%s", m) < 0) {
+ return NULL;
+ }
+ }
+ }
+ return s;
+}
+
+int apol_file_is_policy_path_list(const char *filename)
+{
+ FILE *f = NULL;
+ char *line = NULL;
+ size_t len = 0;
+ int retval = -1, error = 0;
+
+ if (filename == NULL) {
+ error = EINVAL;
+ goto cleanup;
+ }
+ if ((f = fopen(filename, "r")) == NULL) {
+ error = errno;
+ goto cleanup;
+ }
+
+ if (getline(&line, &len, f) < 0) {
+ error = EIO;
+ goto cleanup;
+ }
+ apol_str_trim(line);
+ if (strncmp(line, POLICY_PATH_MAGIC, strlen(POLICY_PATH_MAGIC)) != 0) {
+ retval = 0;
+ goto cleanup;
+ }
+ retval = 1;
+
+ cleanup:
+ if (f)
+ fclose(f);
+ free(line);
+ if (retval < 0)
+ errno = error;
+ return retval;
+}