diff options
Diffstat (limited to 'libapol/src/policy-path.c')
-rw-r--r-- | libapol/src/policy-path.c | 409 |
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; +} |