summaryrefslogtreecommitdiff
path: root/src/genbools.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/genbools.c')
-rw-r--r--src/genbools.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/src/genbools.c b/src/genbools.c
new file mode 100644
index 0000000..e353ef3
--- /dev/null
+++ b/src/genbools.c
@@ -0,0 +1,252 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <sepol/policydb/policydb.h>
+#include <sepol/policydb/conditional.h>
+
+#include "debug.h"
+#include "private.h"
+#include "dso.h"
+
+/* -- Deprecated -- */
+
+static char *strtrim(char *dest, char *source, int size)
+{
+ int i = 0;
+ char *ptr = source;
+ i = 0;
+ while (isspace(*ptr) && i < size) {
+ ptr++;
+ i++;
+ }
+ strncpy(dest, ptr, size);
+ for (i = strlen(dest) - 1; i > 0; i--) {
+ if (!isspace(dest[i]))
+ break;
+ }
+ dest[i + 1] = '\0';
+ return dest;
+}
+
+static int process_boolean(char *buffer, char *name, int namesize, int *val)
+{
+ char name1[BUFSIZ];
+ char *ptr;
+ char *tok = strtok_r(buffer, "=", &ptr);
+ if (tok) {
+ strncpy(name1, tok, BUFSIZ - 1);
+ strtrim(name, name1, namesize - 1);
+ if (name[0] == '#')
+ return 0;
+ tok = strtok_r(NULL, "\0", &ptr);
+ if (tok) {
+ while (isspace(*tok))
+ tok++;
+ *val = -1;
+ if (isdigit(tok[0]))
+ *val = atoi(tok);
+ else if (!strncasecmp(tok, "true", sizeof("true") - 1))
+ *val = 1;
+ else if (!strncasecmp
+ (tok, "false", sizeof("false") - 1))
+ *val = 0;
+ if (*val != 0 && *val != 1) {
+ ERR(NULL, "illegal value for boolean "
+ "%s=%s", name, tok);
+ return -1;
+ }
+
+ }
+ }
+ return 1;
+}
+
+static int load_booleans(struct policydb *policydb, const char *path,
+ int *changesp)
+{
+ FILE *boolf;
+ char *buffer = NULL;
+ size_t size = 0;
+ char localbools[BUFSIZ];
+ char name[BUFSIZ];
+ int val;
+ int errors = 0, changes = 0;
+ struct cond_bool_datum *datum;
+
+ boolf = fopen(path, "r");
+ if (boolf == NULL)
+ goto localbool;
+
+ while (getline(&buffer, &size, boolf) > 0) {
+ int ret = process_boolean(buffer, name, sizeof(name), &val);
+ if (ret == -1)
+ errors++;
+ if (ret == 1) {
+ datum = hashtab_search(policydb->p_bools.table, name);
+ if (!datum) {
+ ERR(NULL, "unknown boolean %s", name);
+ errors++;
+ continue;
+ }
+ if (datum->state != val) {
+ datum->state = val;
+ changes++;
+ }
+ }
+ }
+ fclose(boolf);
+ localbool:
+ snprintf(localbools, sizeof(localbools), "%s.local", path);
+ boolf = fopen(localbools, "r");
+ if (boolf != NULL) {
+ while (getline(&buffer, &size, boolf) > 0) {
+ int ret =
+ process_boolean(buffer, name, sizeof(name), &val);
+ if (ret == -1)
+ errors++;
+ if (ret == 1) {
+ datum =
+ hashtab_search(policydb->p_bools.table,
+ name);
+ if (!datum) {
+ ERR(NULL, "unknown boolean %s", name);
+ errors++;
+ continue;
+ }
+ if (datum->state != val) {
+ datum->state = val;
+ changes++;
+ }
+ }
+ }
+ fclose(boolf);
+ }
+ free(buffer);
+ if (errors)
+ errno = EINVAL;
+ *changesp = changes;
+ return errors ? -1 : 0;
+}
+
+int sepol_genbools(void *data, size_t len, char *booleans)
+{
+ struct policydb policydb;
+ struct policy_file pf;
+ int rc, changes = 0;
+
+ if (policydb_init(&policydb))
+ goto err;
+ if (policydb_from_image(NULL, data, len, &policydb) < 0)
+ goto err;
+
+ if (load_booleans(&policydb, booleans, &changes) < 0) {
+ WARN(NULL, "error while reading %s", booleans);
+ }
+
+ if (!changes)
+ goto out;
+
+ if (evaluate_conds(&policydb) < 0) {
+ ERR(NULL, "error while re-evaluating conditionals");
+ errno = EINVAL;
+ goto err_destroy;
+ }
+
+ policy_file_init(&pf);
+ pf.type = PF_USE_MEMORY;
+ pf.data = data;
+ pf.len = len;
+ rc = policydb_write(&policydb, &pf);
+ if (rc) {
+ ERR(NULL, "unable to write new binary policy image");
+ errno = EINVAL;
+ goto err_destroy;
+ }
+
+ out:
+ policydb_destroy(&policydb);
+ return 0;
+
+ err_destroy:
+ policydb_destroy(&policydb);
+
+ err:
+ return -1;
+}
+
+int hidden sepol_genbools_policydb(policydb_t * policydb, const char *booleans)
+{
+ int rc, changes = 0;
+
+ rc = load_booleans(policydb, booleans, &changes);
+ if (!rc && changes)
+ rc = evaluate_conds(policydb);
+ if (rc)
+ errno = EINVAL;
+ return rc;
+}
+
+/* -- End Deprecated -- */
+
+int sepol_genbools_array(void *data, size_t len, char **names, int *values,
+ int nel)
+{
+ struct policydb policydb;
+ struct policy_file pf;
+ int rc, i, errors = 0;
+ struct cond_bool_datum *datum;
+
+ /* Create policy database from image */
+ if (policydb_init(&policydb))
+ goto err;
+ if (policydb_from_image(NULL, data, len, &policydb) < 0)
+ goto err;
+
+ for (i = 0; i < nel; i++) {
+ datum = hashtab_search(policydb.p_bools.table, names[i]);
+ if (!datum) {
+ ERR(NULL, "boolean %s no longer in policy", names[i]);
+ errors++;
+ continue;
+ }
+ if (values[i] != 0 && values[i] != 1) {
+ ERR(NULL, "illegal value %d for boolean %s",
+ values[i], names[i]);
+ errors++;
+ continue;
+ }
+ datum->state = values[i];
+ }
+
+ if (evaluate_conds(&policydb) < 0) {
+ ERR(NULL, "error while re-evaluating conditionals");
+ errno = EINVAL;
+ goto err_destroy;
+ }
+
+ policy_file_init(&pf);
+ pf.type = PF_USE_MEMORY;
+ pf.data = data;
+ pf.len = len;
+ rc = policydb_write(&policydb, &pf);
+ if (rc) {
+ ERR(NULL, "unable to write binary policy");
+ errno = EINVAL;
+ goto err_destroy;
+ }
+ if (errors) {
+ errno = EINVAL;
+ goto err_destroy;
+ }
+
+ policydb_destroy(&policydb);
+ return 0;
+
+ err_destroy:
+ policydb_destroy(&policydb);
+
+ err:
+ return -1;
+}