#include <stdio.h>
|
|
#include <stdlib.h>
|
#include <ctype.h>
|
#include <errno.h>
|
#include <limits.h>
|
|
#include <sepol/policydb/policydb.h>
|
|
#ifndef __APPLE__
|
#include <stdio_ext.h>
|
#endif
|
|
#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;
|
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;
|
|
#ifdef __APPLE__
|
if ((buffer = (char *)malloc(255 * sizeof(char))) == NULL) {
|
ERR(NULL, "out of memory");
|
return -1;
|
}
|
|
while(fgets(buffer, 255, fp) != NULL) {
|
nread = strlen(buffer);
|
#else
|
size_t len = 0;
|
__fsetlocking(fp, FSETLOCKING_BYCALLER);
|
while ((nread = getline(&buffer, &len, fp)) > 0) {
|
#endif
|
|
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);
|
|
if (!id) {
|
ERR(NULL, "out of memory");
|
free(buffer);
|
fclose(fp);
|
return -1;
|
}
|
|
/* Adding a new user definition. */
|
usrdatum = malloc(sizeof(user_datum_t));
|
if (!usrdatum) {
|
ERR(NULL, "out of memory");
|
free(buffer);
|
free(id);
|
fclose(fp);
|
return -1;
|
}
|
|
user_datum_init(usrdatum);
|
usrdatum->s.value = ++policydb->p_users.nprim;
|
if (hashtab_insert(policydb->p_users.table,
|
id, (hashtab_datum_t) usrdatum)) {
|
ERR(NULL, "out of memory");
|
free(buffer);
|
free(id);
|
user_datum_destroy(usrdatum);
|
free(usrdatum);
|
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 && (!isspace(*p) || strncasecmp(p + 1, "range", 5)))
|
p++;
|
if (!(*p) || p == q)
|
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 -- */
|