summaryrefslogtreecommitdiff
path: root/src/genusers.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/genusers.c')
-rw-r--r--src/genusers.c318
1 files changed, 318 insertions, 0 deletions
diff --git a/src/genusers.c b/src/genusers.c
new file mode 100644
index 0000000..44f94e9
--- /dev/null
+++ b/src/genusers.c
@@ -0,0 +1,318 @@
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <sepol/policydb/policydb.h>
+#include <stdarg.h>
+
+#include "debug.h"
+#include "private.h"
+#include "dso.h"
+#include "mls.h"
+
+/* -- Deprecated -- */
+
+void sepol_set_delusers(int on __attribute((unused)))
+{
+ WARN(NULL, "Deprecated interface");
+}
+
+#undef BADLINE
+#define BADLINE() { \
+ ERR(NULL, "invalid entry %s (%s:%u)", \
+ buffer, path, lineno); \
+ continue; \
+}
+
+static int load_users(struct policydb *policydb, const char *path)
+{
+ FILE *fp;
+ char *buffer = NULL, *p, *q, oldc;
+ size_t len = 0;
+ ssize_t nread;
+ unsigned lineno = 0, islist = 0, bit;
+ user_datum_t *usrdatum;
+ role_datum_t *roldatum;
+ ebitmap_node_t *rnode;
+
+ fp = fopen(path, "r");
+ if (fp == NULL)
+ return -1;
+ __fsetlocking(fp, FSETLOCKING_BYCALLER);
+
+ while ((nread = getline(&buffer, &len, fp)) > 0) {
+ lineno++;
+ if (buffer[nread - 1] == '\n')
+ buffer[nread - 1] = 0;
+ p = buffer;
+ while (*p && isspace(*p))
+ p++;
+ if (!(*p) || *p == '#')
+ continue;
+
+ if (strncasecmp(p, "user", 4))
+ BADLINE();
+ p += 4;
+ if (!isspace(*p))
+ BADLINE();
+ while (*p && isspace(*p))
+ p++;
+ if (!(*p))
+ BADLINE();
+ q = p;
+ while (*p && !isspace(*p))
+ p++;
+ if (!(*p))
+ BADLINE();
+ *p++ = 0;
+
+ usrdatum = hashtab_search(policydb->p_users.table, q);
+ if (usrdatum) {
+ /* Replacing an existing user definition. */
+ ebitmap_destroy(&usrdatum->roles.roles);
+ ebitmap_init(&usrdatum->roles.roles);
+ } else {
+ char *id = strdup(q);
+
+ /* Adding a new user definition. */
+ usrdatum =
+ (user_datum_t *) malloc(sizeof(user_datum_t));
+ if (!id || !usrdatum) {
+ ERR(NULL, "out of memory");
+ free(buffer);
+ fclose(fp);
+ return -1;
+ }
+ memset(usrdatum, 0, sizeof(user_datum_t));
+ usrdatum->s.value = ++policydb->p_users.nprim;
+ ebitmap_init(&usrdatum->roles.roles);
+ if (hashtab_insert(policydb->p_users.table,
+ id, (hashtab_datum_t) usrdatum)) {
+ ERR(NULL, "out of memory");
+ free(buffer);
+ fclose(fp);
+ return -1;
+ }
+ }
+
+ while (*p && isspace(*p))
+ p++;
+ if (!(*p))
+ BADLINE();
+ if (strncasecmp(p, "roles", 5))
+ BADLINE();
+ p += 5;
+ if (!isspace(*p))
+ BADLINE();
+ while (*p && isspace(*p))
+ p++;
+ if (!(*p))
+ BADLINE();
+ if (*p == '{') {
+ islist = 1;
+ p++;
+ } else
+ islist = 0;
+
+ oldc = 0;
+ do {
+ while (*p && isspace(*p))
+ p++;
+ if (!(*p))
+ break;
+
+ q = p;
+ while (*p && *p != ';' && *p != '}' && !isspace(*p))
+ p++;
+ if (!(*p))
+ break;
+ if (*p == '}')
+ islist = 0;
+ oldc = *p;
+ *p++ = 0;
+ if (!q[0])
+ break;
+
+ roldatum = hashtab_search(policydb->p_roles.table, q);
+ if (!roldatum) {
+ ERR(NULL, "undefined role %s (%s:%u)",
+ q, path, lineno);
+ continue;
+ }
+ /* Set the role and every role it dominates */
+ ebitmap_for_each_bit(&roldatum->dominates, rnode, bit) {
+ if (ebitmap_node_get_bit(rnode, bit))
+ if (ebitmap_set_bit
+ (&usrdatum->roles.roles, bit, 1)) {
+ ERR(NULL, "out of memory");
+ free(buffer);
+ fclose(fp);
+ return -1;
+ }
+ }
+ } while (islist);
+ if (oldc == 0)
+ BADLINE();
+
+ if (policydb->mls) {
+ context_struct_t context;
+ char *scontext, *r, *s;
+
+ while (*p && isspace(*p))
+ p++;
+ if (!(*p))
+ BADLINE();
+ if (strncasecmp(p, "level", 5))
+ BADLINE();
+ p += 5;
+ if (!isspace(*p))
+ BADLINE();
+ while (*p && isspace(*p))
+ p++;
+ if (!(*p))
+ BADLINE();
+ q = p;
+ while (*p && strncasecmp(p, "range", 5))
+ p++;
+ if (!(*p))
+ BADLINE();
+ *--p = 0;
+ p++;
+
+ scontext = malloc(p - q);
+ if (!scontext) {
+ ERR(NULL, "out of memory");
+ free(buffer);
+ fclose(fp);
+ return -1;
+ }
+ r = scontext;
+ s = q;
+ while (*s) {
+ if (!isspace(*s))
+ *r++ = *s;
+ s++;
+ }
+ *r = 0;
+ r = scontext;
+
+ context_init(&context);
+ if (mls_context_to_sid(policydb, oldc, &r, &context) <
+ 0) {
+ ERR(NULL, "invalid level %s (%s:%u)", scontext,
+ path, lineno);
+ free(scontext);
+ continue;
+
+ }
+ free(scontext);
+ memcpy(&usrdatum->dfltlevel, &context.range.level[0],
+ sizeof(usrdatum->dfltlevel));
+
+ if (strncasecmp(p, "range", 5))
+ BADLINE();
+ p += 5;
+ if (!isspace(*p))
+ BADLINE();
+ while (*p && isspace(*p))
+ p++;
+ if (!(*p))
+ BADLINE();
+ q = p;
+ while (*p && *p != ';')
+ p++;
+ if (!(*p))
+ BADLINE();
+ *p++ = 0;
+
+ scontext = malloc(p - q);
+ if (!scontext) {
+ ERR(NULL, "out of memory");
+ free(buffer);
+ fclose(fp);
+ return -1;
+ }
+ r = scontext;
+ s = q;
+ while (*s) {
+ if (!isspace(*s))
+ *r++ = *s;
+ s++;
+ }
+ *r = 0;
+ r = scontext;
+
+ context_init(&context);
+ if (mls_context_to_sid(policydb, oldc, &r, &context) <
+ 0) {
+ ERR(NULL, "invalid range %s (%s:%u)", scontext,
+ path, lineno);
+ free(scontext);
+ continue;
+ }
+ free(scontext);
+ memcpy(&usrdatum->range, &context.range,
+ sizeof(usrdatum->range));
+ }
+ }
+
+ free(buffer);
+ fclose(fp);
+ return 0;
+}
+
+int sepol_genusers(void *data, size_t len,
+ const char *usersdir, void **newdata, size_t * newlen)
+{
+ struct policydb policydb;
+ char path[PATH_MAX];
+
+ /* Construct policy database */
+ if (policydb_init(&policydb))
+ goto err;
+ if (policydb_from_image(NULL, data, len, &policydb) < 0)
+ goto err;
+
+ /* Load locally defined users. */
+ snprintf(path, sizeof path, "%s/local.users", usersdir);
+ if (load_users(&policydb, path) < 0)
+ goto err_destroy;
+
+ /* Write policy database */
+ if (policydb_to_image(NULL, &policydb, newdata, newlen) < 0)
+ goto err_destroy;
+
+ policydb_destroy(&policydb);
+ return 0;
+
+ err_destroy:
+ policydb_destroy(&policydb);
+
+ err:
+ return -1;
+}
+
+int hidden sepol_genusers_policydb(policydb_t * policydb, const char *usersdir)
+{
+ char path[PATH_MAX];
+
+ /* Load locally defined users. */
+ snprintf(path, sizeof path, "%s/local.users", usersdir);
+ if (load_users(policydb, path) < 0) {
+ ERR(NULL, "unable to load local.users: %s", strerror(errno));
+ return -1;
+ }
+
+ if (policydb_reindex_users(policydb) < 0) {
+ ERR(NULL, "unable to reindex users: %s", strerror(errno));
+ return -1;
+
+ }
+
+ return 0;
+}
+
+/* -- End Deprecated -- */