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