Home | History | Annotate | Download | only in src
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <ctype.h>
      4 #include <errno.h>
      5 
      6 #include <sepol/policydb/policydb.h>
      7 #include <sepol/policydb/conditional.h>
      8 
      9 #include "debug.h"
     10 #include "private.h"
     11 #include "dso.h"
     12 
     13 /* -- Deprecated -- */
     14 
     15 static char *strtrim(char *dest, char *source, int size)
     16 {
     17 	int i = 0;
     18 	char *ptr = source;
     19 	i = 0;
     20 	while (isspace(*ptr) && i < size) {
     21 		ptr++;
     22 		i++;
     23 	}
     24 	strncpy(dest, ptr, size);
     25 	for (i = strlen(dest) - 1; i > 0; i--) {
     26 		if (!isspace(dest[i]))
     27 			break;
     28 	}
     29 	dest[i + 1] = '\0';
     30 	return dest;
     31 }
     32 
     33 static int process_boolean(char *buffer, char *name, int namesize, int *val)
     34 {
     35 	char name1[BUFSIZ];
     36 	char *ptr = NULL;
     37 	char *tok;
     38 
     39 	/* Skip spaces */
     40 	while (isspace(buffer[0]))
     41 		buffer++;
     42 	/* Ignore comments */
     43 	if (buffer[0] == '#')
     44 		return 0;
     45 
     46 	tok = strtok_r(buffer, "=", &ptr);
     47 	if (!tok) {
     48 		ERR(NULL, "illegal boolean definition %s", buffer);
     49 		return -1;
     50 	}
     51 	strncpy(name1, tok, BUFSIZ - 1);
     52 	strtrim(name, name1, namesize - 1);
     53 
     54 	tok = strtok_r(NULL, "\0", &ptr);
     55 	if (!tok) {
     56 		ERR(NULL, "illegal boolean definition %s=%s", name, buffer);
     57 		return -1;
     58 	}
     59 
     60 	while (isspace(*tok))
     61 		tok++;
     62 
     63 	*val = -1;
     64 	if (isdigit(tok[0]))
     65 		*val = atoi(tok);
     66 	else if (!strncasecmp(tok, "true", sizeof("true") - 1))
     67 		*val = 1;
     68 	else if (!strncasecmp(tok, "false", sizeof("false") - 1))
     69 		*val = 0;
     70 	if (*val != 0 && *val != 1) {
     71 		ERR(NULL, "illegal value for boolean %s=%s", name, tok);
     72 		return -1;
     73 	}
     74 	return 1;
     75 }
     76 
     77 static int load_booleans(struct policydb *policydb, const char *path,
     78 			 int *changesp)
     79 {
     80 	FILE *boolf;
     81 	char *buffer = NULL;
     82 	char localbools[BUFSIZ];
     83 	char name[BUFSIZ];
     84 	int val;
     85 	int errors = 0, changes = 0;
     86 	struct cond_bool_datum *datum;
     87 
     88 	boolf = fopen(path, "r");
     89 	if (boolf == NULL)
     90 		goto localbool;
     91 
     92 #ifdef __APPLE__
     93         if ((buffer = (char *)malloc(255 * sizeof(char))) == NULL) {
     94           ERR(NULL, "out of memory");
     95 	  return -1;
     96 	}
     97 
     98         while(fgets(buffer, 255, boolf) != NULL) {
     99 #else
    100 	size_t size = 0;
    101 	while (getline(&buffer, &size, boolf) > 0) {
    102 #endif
    103 		int ret = process_boolean(buffer, name, sizeof(name), &val);
    104 		if (ret == -1)
    105 			errors++;
    106 		if (ret == 1) {
    107 			datum = hashtab_search(policydb->p_bools.table, name);
    108 			if (!datum) {
    109 				ERR(NULL, "unknown boolean %s", name);
    110 				errors++;
    111 				continue;
    112 			}
    113 			if (datum->state != val) {
    114 				datum->state = val;
    115 				changes++;
    116 			}
    117 		}
    118 	}
    119 	fclose(boolf);
    120       localbool:
    121 	snprintf(localbools, sizeof(localbools), "%s.local", path);
    122 	boolf = fopen(localbools, "r");
    123 	if (boolf != NULL) {
    124 
    125 #ifdef __APPLE__
    126 
    127 	  while(fgets(buffer, 255, boolf) != NULL) {
    128 #else
    129 
    130 	    while (getline(&buffer, &size, boolf) > 0) {
    131 #endif
    132 			int ret =
    133 			    process_boolean(buffer, name, sizeof(name), &val);
    134 			if (ret == -1)
    135 				errors++;
    136 			if (ret == 1) {
    137 				datum =
    138 				    hashtab_search(policydb->p_bools.table,
    139 						   name);
    140 				if (!datum) {
    141 					ERR(NULL, "unknown boolean %s", name);
    142 					errors++;
    143 					continue;
    144 				}
    145 				if (datum->state != val) {
    146 					datum->state = val;
    147 					changes++;
    148 				}
    149 			}
    150 		}
    151 		fclose(boolf);
    152 	}
    153 	free(buffer);
    154 	if (errors)
    155 		errno = EINVAL;
    156 	*changesp = changes;
    157 	return errors ? -1 : 0;
    158 }
    159 
    160 int sepol_genbools(void *data, size_t len, const char *booleans)
    161 {
    162 	struct policydb policydb;
    163 	struct policy_file pf;
    164 	int rc, changes = 0;
    165 
    166 	if (policydb_init(&policydb))
    167 		goto err;
    168 	if (policydb_from_image(NULL, data, len, &policydb) < 0)
    169 		goto err;
    170 
    171 	if (load_booleans(&policydb, booleans, &changes) < 0) {
    172 		WARN(NULL, "error while reading %s", booleans);
    173 	}
    174 
    175 	if (!changes)
    176 		goto out;
    177 
    178 	if (evaluate_conds(&policydb) < 0) {
    179 		ERR(NULL, "error while re-evaluating conditionals");
    180 		errno = EINVAL;
    181 		goto err_destroy;
    182 	}
    183 
    184 	policy_file_init(&pf);
    185 	pf.type = PF_USE_MEMORY;
    186 	pf.data = data;
    187 	pf.len = len;
    188 	rc = policydb_write(&policydb, &pf);
    189 	if (rc) {
    190 		ERR(NULL, "unable to write new binary policy image");
    191 		errno = EINVAL;
    192 		goto err_destroy;
    193 	}
    194 
    195       out:
    196 	policydb_destroy(&policydb);
    197 	return 0;
    198 
    199       err_destroy:
    200 	policydb_destroy(&policydb);
    201 
    202       err:
    203 	return -1;
    204 }
    205 
    206 int hidden sepol_genbools_policydb(policydb_t * policydb, const char *booleans)
    207 {
    208 	int rc, changes = 0;
    209 
    210 	rc = load_booleans(policydb, booleans, &changes);
    211 	if (!rc && changes)
    212 		rc = evaluate_conds(policydb);
    213 	if (rc)
    214 		errno = EINVAL;
    215 	return rc;
    216 }
    217 
    218 /* -- End Deprecated -- */
    219 
    220 int sepol_genbools_array(void *data, size_t len, char **names, int *values,
    221 			 int nel)
    222 {
    223 	struct policydb policydb;
    224 	struct policy_file pf;
    225 	int rc, i, errors = 0;
    226 	struct cond_bool_datum *datum;
    227 
    228 	/* Create policy database from image */
    229 	if (policydb_init(&policydb))
    230 		goto err;
    231 	if (policydb_from_image(NULL, data, len, &policydb) < 0)
    232 		goto err;
    233 
    234 	for (i = 0; i < nel; i++) {
    235 		datum = hashtab_search(policydb.p_bools.table, names[i]);
    236 		if (!datum) {
    237 			ERR(NULL, "boolean %s no longer in policy", names[i]);
    238 			errors++;
    239 			continue;
    240 		}
    241 		if (values[i] != 0 && values[i] != 1) {
    242 			ERR(NULL, "illegal value %d for boolean %s",
    243 			    values[i], names[i]);
    244 			errors++;
    245 			continue;
    246 		}
    247 		datum->state = values[i];
    248 	}
    249 
    250 	if (evaluate_conds(&policydb) < 0) {
    251 		ERR(NULL, "error while re-evaluating conditionals");
    252 		errno = EINVAL;
    253 		goto err_destroy;
    254 	}
    255 
    256 	policy_file_init(&pf);
    257 	pf.type = PF_USE_MEMORY;
    258 	pf.data = data;
    259 	pf.len = len;
    260 	rc = policydb_write(&policydb, &pf);
    261 	if (rc) {
    262 		ERR(NULL, "unable to write binary policy");
    263 		errno = EINVAL;
    264 		goto err_destroy;
    265 	}
    266 	if (errors) {
    267 		errno = EINVAL;
    268 		goto err_destroy;
    269 	}
    270 
    271 	policydb_destroy(&policydb);
    272 	return 0;
    273 
    274       err_destroy:
    275 	policydb_destroy(&policydb);
    276 
    277       err:
    278 	return -1;
    279 }
    280