Home | History | Annotate | Download | only in src
      1 #include <stdio.h>
      2 
      3 #include <stdlib.h>
      4 #include <ctype.h>
      5 #include <errno.h>
      6 #include <limits.h>
      7 
      8 #include <sepol/policydb/policydb.h>
      9 
     10 #ifndef DARWIN
     11 #include <stdio_ext.h>
     12 #endif
     13 
     14 #include <stdarg.h>
     15 
     16 #include "debug.h"
     17 #include "private.h"
     18 #include "dso.h"
     19 #include "mls.h"
     20 
     21 /* -- Deprecated -- */
     22 
     23 void sepol_set_delusers(int on __attribute((unused)))
     24 {
     25 	WARN(NULL, "Deprecated interface");
     26 }
     27 
     28 #undef BADLINE
     29 #define BADLINE() { \
     30 	ERR(NULL, "invalid entry %s (%s:%u)", \
     31 		buffer, path, lineno); \
     32 	continue; \
     33 }
     34 
     35 static int load_users(struct policydb *policydb, const char *path)
     36 {
     37 	FILE *fp;
     38 	char *buffer = NULL, *p, *q, oldc;
     39 	size_t len = 0;
     40 	ssize_t nread;
     41 	unsigned lineno = 0, islist = 0, bit;
     42 	user_datum_t *usrdatum;
     43 	role_datum_t *roldatum;
     44 	ebitmap_node_t *rnode;
     45 
     46 	fp = fopen(path, "r");
     47 	if (fp == NULL)
     48 		return -1;
     49 
     50 #ifdef DARWIN
     51 	if ((buffer = (char *)malloc(255 * sizeof(char))) == NULL) {
     52 	  ERR(NULL, "out of memory");
     53 	  return -1;
     54 	}
     55 
     56 	while(fgets(buffer, 255, fp) != NULL) {
     57 #else
     58 	__fsetlocking(fp, FSETLOCKING_BYCALLER);
     59 	while ((nread = getline(&buffer, &len, fp)) > 0) {
     60 #endif
     61 
     62 		lineno++;
     63 		if (buffer[nread - 1] == '\n')
     64 			buffer[nread - 1] = 0;
     65 		p = buffer;
     66 		while (*p && isspace(*p))
     67 			p++;
     68 		if (!(*p) || *p == '#')
     69 			continue;
     70 
     71 		if (strncasecmp(p, "user", 4))
     72 			BADLINE();
     73 		p += 4;
     74 		if (!isspace(*p))
     75 			BADLINE();
     76 		while (*p && isspace(*p))
     77 			p++;
     78 		if (!(*p))
     79 			BADLINE();
     80 		q = p;
     81 		while (*p && !isspace(*p))
     82 			p++;
     83 		if (!(*p))
     84 			BADLINE();
     85 		*p++ = 0;
     86 
     87 		usrdatum = hashtab_search(policydb->p_users.table, q);
     88 		if (usrdatum) {
     89 			/* Replacing an existing user definition. */
     90 			ebitmap_destroy(&usrdatum->roles.roles);
     91 			ebitmap_init(&usrdatum->roles.roles);
     92 		} else {
     93 			char *id = strdup(q);
     94 
     95 			if (!id) {
     96 				ERR(NULL, "out of memory");
     97 				free(buffer);
     98 				fclose(fp);
     99 				return -1;
    100 			}
    101 
    102 			/* Adding a new user definition. */
    103 			usrdatum = malloc(sizeof(user_datum_t));
    104 			if (!usrdatum) {
    105 				ERR(NULL, "out of memory");
    106 				free(buffer);
    107 				free(id);
    108 				fclose(fp);
    109 				return -1;
    110 			}
    111 
    112 			user_datum_init(usrdatum);
    113 			usrdatum->s.value = ++policydb->p_users.nprim;
    114 			if (hashtab_insert(policydb->p_users.table,
    115 					   id, (hashtab_datum_t) usrdatum)) {
    116 				ERR(NULL, "out of memory");
    117 				free(buffer);
    118 				free(id);
    119 				user_datum_destroy(usrdatum);
    120 				free(usrdatum);
    121 				fclose(fp);
    122 				return -1;
    123 			}
    124 		}
    125 
    126 		while (*p && isspace(*p))
    127 			p++;
    128 		if (!(*p))
    129 			BADLINE();
    130 		if (strncasecmp(p, "roles", 5))
    131 			BADLINE();
    132 		p += 5;
    133 		if (!isspace(*p))
    134 			BADLINE();
    135 		while (*p && isspace(*p))
    136 			p++;
    137 		if (!(*p))
    138 			BADLINE();
    139 		if (*p == '{') {
    140 			islist = 1;
    141 			p++;
    142 		} else
    143 			islist = 0;
    144 
    145 		oldc = 0;
    146 		do {
    147 			while (*p && isspace(*p))
    148 				p++;
    149 			if (!(*p))
    150 				break;
    151 
    152 			q = p;
    153 			while (*p && *p != ';' && *p != '}' && !isspace(*p))
    154 				p++;
    155 			if (!(*p))
    156 				break;
    157 			if (*p == '}')
    158 				islist = 0;
    159 			oldc = *p;
    160 			*p++ = 0;
    161 			if (!q[0])
    162 				break;
    163 
    164 			roldatum = hashtab_search(policydb->p_roles.table, q);
    165 			if (!roldatum) {
    166 				ERR(NULL, "undefined role %s (%s:%u)",
    167 				    q, path, lineno);
    168 				continue;
    169 			}
    170 			/* Set the role and every role it dominates */
    171 			ebitmap_for_each_bit(&roldatum->dominates, rnode, bit) {
    172 				if (ebitmap_node_get_bit(rnode, bit))
    173 					if (ebitmap_set_bit
    174 					    (&usrdatum->roles.roles, bit, 1)) {
    175 						ERR(NULL, "out of memory");
    176 						free(buffer);
    177 						fclose(fp);
    178 						return -1;
    179 					}
    180 			}
    181 		} while (islist);
    182 		if (oldc == 0)
    183 			BADLINE();
    184 
    185 		if (policydb->mls) {
    186 			context_struct_t context;
    187 			char *scontext, *r, *s;
    188 
    189 			while (*p && isspace(*p))
    190 				p++;
    191 			if (!(*p))
    192 				BADLINE();
    193 			if (strncasecmp(p, "level", 5))
    194 				BADLINE();
    195 			p += 5;
    196 			if (!isspace(*p))
    197 				BADLINE();
    198 			while (*p && isspace(*p))
    199 				p++;
    200 			if (!(*p))
    201 				BADLINE();
    202 			q = p;
    203 			while (*p && strncasecmp(p, "range", 5))
    204 				p++;
    205 			if (!(*p))
    206 				BADLINE();
    207 			*--p = 0;
    208 			p++;
    209 
    210 			scontext = malloc(p - q);
    211 			if (!scontext) {
    212 				ERR(NULL, "out of memory");
    213 				free(buffer);
    214 				fclose(fp);
    215 				return -1;
    216 			}
    217 			r = scontext;
    218 			s = q;
    219 			while (*s) {
    220 				if (!isspace(*s))
    221 					*r++ = *s;
    222 				s++;
    223 			}
    224 			*r = 0;
    225 			r = scontext;
    226 
    227 			context_init(&context);
    228 			if (mls_context_to_sid(policydb, oldc, &r, &context) <
    229 			    0) {
    230 				ERR(NULL, "invalid level %s (%s:%u)", scontext,
    231 				    path, lineno);
    232 				free(scontext);
    233 				continue;
    234 
    235 			}
    236 			free(scontext);
    237 			memcpy(&usrdatum->dfltlevel, &context.range.level[0],
    238 			       sizeof(usrdatum->dfltlevel));
    239 
    240 			if (strncasecmp(p, "range", 5))
    241 				BADLINE();
    242 			p += 5;
    243 			if (!isspace(*p))
    244 				BADLINE();
    245 			while (*p && isspace(*p))
    246 				p++;
    247 			if (!(*p))
    248 				BADLINE();
    249 			q = p;
    250 			while (*p && *p != ';')
    251 				p++;
    252 			if (!(*p))
    253 				BADLINE();
    254 			*p++ = 0;
    255 
    256 			scontext = malloc(p - q);
    257 			if (!scontext) {
    258 				ERR(NULL, "out of memory");
    259 				free(buffer);
    260 				fclose(fp);
    261 				return -1;
    262 			}
    263 			r = scontext;
    264 			s = q;
    265 			while (*s) {
    266 				if (!isspace(*s))
    267 					*r++ = *s;
    268 				s++;
    269 			}
    270 			*r = 0;
    271 			r = scontext;
    272 
    273 			context_init(&context);
    274 			if (mls_context_to_sid(policydb, oldc, &r, &context) <
    275 			    0) {
    276 				ERR(NULL, "invalid range %s (%s:%u)", scontext,
    277 				    path, lineno);
    278 				free(scontext);
    279 				continue;
    280 			}
    281 			free(scontext);
    282 			memcpy(&usrdatum->range, &context.range,
    283 			       sizeof(usrdatum->range));
    284 		}
    285 	}
    286 
    287 	free(buffer);
    288 	fclose(fp);
    289 	return 0;
    290 }
    291 
    292 int sepol_genusers(void *data, size_t len,
    293 		   const char *usersdir, void **newdata, size_t * newlen)
    294 {
    295 	struct policydb policydb;
    296 	char path[PATH_MAX];
    297 
    298 	/* Construct policy database */
    299 	if (policydb_init(&policydb))
    300 		goto err;
    301 	if (policydb_from_image(NULL, data, len, &policydb) < 0)
    302 		goto err;
    303 
    304 	/* Load locally defined users. */
    305 	snprintf(path, sizeof path, "%s/local.users", usersdir);
    306 	if (load_users(&policydb, path) < 0)
    307 		goto err_destroy;
    308 
    309 	/* Write policy database */
    310 	if (policydb_to_image(NULL, &policydb, newdata, newlen) < 0)
    311 		goto err_destroy;
    312 
    313 	policydb_destroy(&policydb);
    314 	return 0;
    315 
    316       err_destroy:
    317 	policydb_destroy(&policydb);
    318 
    319       err:
    320 	return -1;
    321 }
    322 
    323 int hidden sepol_genusers_policydb(policydb_t * policydb, const char *usersdir)
    324 {
    325 	char path[PATH_MAX];
    326 
    327 	/* Load locally defined users. */
    328 	snprintf(path, sizeof path, "%s/local.users", usersdir);
    329 	if (load_users(policydb, path) < 0) {
    330 		ERR(NULL, "unable to load local.users: %s", strerror(errno));
    331 		return -1;
    332 	}
    333 
    334 	if (policydb_reindex_users(policydb) < 0) {
    335 		ERR(NULL, "unable to reindex users: %s", strerror(errno));
    336 		return -1;
    337 
    338 	}
    339 
    340 	return 0;
    341 }
    342 
    343 /* -- End Deprecated -- */
    344