Home | History | Annotate | Download | only in src
      1 #include <netinet/in.h>
      2 #include <stdlib.h>
      3 
      4 #include "debug.h"
      5 #include "context.h"
      6 #include "handle.h"
      7 
      8 #include <sepol/ibpkey_record.h>
      9 #include <sepol/policydb/policydb.h>
     10 #include "ibpkey_internal.h"
     11 
     12 /* Create a low level ibpkey structure from
     13  * a high level representation
     14  */
     15 static int ibpkey_from_record(sepol_handle_t *handle,
     16 			      const policydb_t *policydb,
     17 			      ocontext_t **ibpkey, const sepol_ibpkey_t *data)
     18 {
     19 	ocontext_t *tmp_ibpkey = NULL;
     20 	context_struct_t *tmp_con = NULL;
     21 	char *subnet_prefix_buf = NULL;
     22 	int low = sepol_ibpkey_get_low(data);
     23 	int high = sepol_ibpkey_get_high(data);
     24 
     25 	tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey));
     26 	if (!tmp_ibpkey)
     27 		goto omem;
     28 
     29 	tmp_ibpkey->u.ibpkey.subnet_prefix = sepol_ibpkey_get_subnet_prefix_bytes(data);
     30 
     31 	/* Pkey range */
     32 	tmp_ibpkey->u.ibpkey.low_pkey = low;
     33 	tmp_ibpkey->u.ibpkey.high_pkey = high;
     34 	if (tmp_ibpkey->u.ibpkey.low_pkey > tmp_ibpkey->u.ibpkey.high_pkey) {
     35 		ERR(handle, "low ibpkey %d exceeds high ibpkey %d",
     36 		    tmp_ibpkey->u.ibpkey.low_pkey, tmp_ibpkey->u.ibpkey.high_pkey);
     37 		goto err;
     38 	}
     39 
     40 	/* Context */
     41 	if (context_from_record(handle, policydb, &tmp_con,
     42 				sepol_ibpkey_get_con(data)) < 0)
     43 		goto err;
     44 	context_cpy(&tmp_ibpkey->context[0], tmp_con);
     45 	context_destroy(tmp_con);
     46 	free(tmp_con);
     47 	tmp_con = NULL;
     48 
     49 	*ibpkey = tmp_ibpkey;
     50 	return STATUS_SUCCESS;
     51 
     52 omem:
     53 	ERR(handle, "out of memory");
     54 
     55 err:
     56 	if (tmp_ibpkey) {
     57 		context_destroy(&tmp_ibpkey->context[0]);
     58 		free(tmp_ibpkey);
     59 	}
     60 	context_destroy(tmp_con);
     61 	free(tmp_con);
     62 	free(subnet_prefix_buf);
     63 	ERR(handle, "could not create ibpkey structure");
     64 	return STATUS_ERR;
     65 }
     66 
     67 static int ibpkey_to_record(sepol_handle_t *handle,
     68 			    const policydb_t *policydb,
     69 			    ocontext_t *ibpkey, sepol_ibpkey_t **record)
     70 {
     71 	context_struct_t *con = &ibpkey->context[0];
     72 	sepol_context_t *tmp_con = NULL;
     73 	sepol_ibpkey_t *tmp_record = NULL;
     74 
     75 	if (sepol_ibpkey_create(handle, &tmp_record) < 0)
     76 		goto err;
     77 
     78 	sepol_ibpkey_set_subnet_prefix_bytes(tmp_record,
     79 					     ibpkey->u.ibpkey.subnet_prefix);
     80 
     81 	sepol_ibpkey_set_range(tmp_record, ibpkey->u.ibpkey.low_pkey,
     82 			       ibpkey->u.ibpkey.high_pkey);
     83 
     84 	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
     85 		goto err;
     86 
     87 	if (sepol_ibpkey_set_con(handle, tmp_record, tmp_con) < 0)
     88 		goto err;
     89 
     90 	sepol_context_free(tmp_con);
     91 	*record = tmp_record;
     92 	return STATUS_SUCCESS;
     93 
     94 err:
     95 	ERR(handle, "could not convert ibpkey to record");
     96 	sepol_context_free(tmp_con);
     97 	sepol_ibpkey_free(tmp_record);
     98 	return STATUS_ERR;
     99 }
    100 
    101 /* Return the number of ibpkeys */
    102 extern int sepol_ibpkey_count(sepol_handle_t *handle __attribute__ ((unused)),
    103 			      const sepol_policydb_t *p, unsigned int *response)
    104 {
    105 	unsigned int count = 0;
    106 	ocontext_t *c, *head;
    107 	const policydb_t *policydb = &p->p;
    108 
    109 	head = policydb->ocontexts[OCON_IBPKEY];
    110 	for (c = head; c; c = c->next)
    111 		count++;
    112 
    113 	*response = count;
    114 
    115 	return STATUS_SUCCESS;
    116 }
    117 
    118 /* Check if a ibpkey exists */
    119 int sepol_ibpkey_exists(sepol_handle_t *handle __attribute__ ((unused)),
    120 			const sepol_policydb_t *p,
    121 			const sepol_ibpkey_key_t *key, int *response)
    122 {
    123 	const policydb_t *policydb = &p->p;
    124 	ocontext_t *c, *head;
    125 	int low, high;
    126 	uint64_t subnet_prefix;
    127 
    128 	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
    129 
    130 	head = policydb->ocontexts[OCON_IBPKEY];
    131 	for (c = head; c; c = c->next) {
    132 		uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix;
    133 		uint16_t low2 = c->u.ibpkey.low_pkey;
    134 		uint16_t high2 = c->u.ibpkey.high_pkey;
    135 
    136 		if (low2 == low &&
    137 		    high2 == high &&
    138 		    subnet_prefix == subnet_prefix2) {
    139 			*response = 1;
    140 			return STATUS_SUCCESS;
    141 		}
    142 	}
    143 
    144 	*response = 0;
    145 	return STATUS_SUCCESS;
    146 }
    147 
    148 /* Query a ibpkey */
    149 int sepol_ibpkey_query(sepol_handle_t *handle,
    150 		       const sepol_policydb_t *p,
    151 		       const sepol_ibpkey_key_t *key, sepol_ibpkey_t **response)
    152 {
    153 	const policydb_t *policydb = &p->p;
    154 	ocontext_t *c, *head;
    155 	int low, high;
    156 	uint64_t subnet_prefix;
    157 
    158 	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
    159 
    160 	head = policydb->ocontexts[OCON_IBPKEY];
    161 	for (c = head; c; c = c->next) {
    162 		uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix;
    163 		int low2 = c->u.ibpkey.low_pkey;
    164 		int high2 = c->u.ibpkey.high_pkey;
    165 
    166 		if (low2 == low &&
    167 		    high2 == high &&
    168 		    subnet_prefix == subnet_prefix2) {
    169 			if (ibpkey_to_record(handle, policydb, c, response) < 0)
    170 				goto err;
    171 			return STATUS_SUCCESS;
    172 		}
    173 	}
    174 
    175 	*response = NULL;
    176 	return STATUS_SUCCESS;
    177 
    178 err:
    179 	ERR(handle, "could not query ibpkey subnet prefix: %#lx range %u - %u exists",
    180 	    subnet_prefix, low, high);
    181 	return STATUS_ERR;
    182 }
    183 
    184 /* Load a ibpkey into policy */
    185 int sepol_ibpkey_modify(sepol_handle_t *handle,
    186 			sepol_policydb_t *p,
    187 			const sepol_ibpkey_key_t *key, const sepol_ibpkey_t *data)
    188 {
    189 	policydb_t *policydb = &p->p;
    190 	ocontext_t *ibpkey = NULL;
    191 	int low, high;
    192 	uint64_t subnet_prefix;
    193 
    194 	sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high);
    195 
    196 	if (ibpkey_from_record(handle, policydb, &ibpkey, data) < 0)
    197 		goto err;
    198 
    199 	/* Attach to context list */
    200 	ibpkey->next = policydb->ocontexts[OCON_IBPKEY];
    201 	policydb->ocontexts[OCON_IBPKEY] = ibpkey;
    202 
    203 	return STATUS_SUCCESS;
    204 
    205 err:
    206 	ERR(handle, "could not load ibpkey subnet prefix: %#lx range %u - %u exists",
    207 	    subnet_prefix, low, high);
    208 	if (ibpkey) {
    209 		context_destroy(&ibpkey->context[0]);
    210 		free(ibpkey);
    211 	}
    212 	return STATUS_ERR;
    213 }
    214 
    215 int sepol_ibpkey_iterate(sepol_handle_t *handle,
    216 			 const sepol_policydb_t *p,
    217 			 int (*fn)(const sepol_ibpkey_t *ibpkey,
    218 				   void *fn_arg), void *arg)
    219 {
    220 	const policydb_t *policydb = &p->p;
    221 	ocontext_t *c, *head;
    222 	sepol_ibpkey_t *ibpkey = NULL;
    223 
    224 	head = policydb->ocontexts[OCON_IBPKEY];
    225 	for (c = head; c; c = c->next) {
    226 		int status;
    227 
    228 		if (ibpkey_to_record(handle, policydb, c, &ibpkey) < 0)
    229 			goto err;
    230 
    231 		/* Invoke handler */
    232 		status = fn(ibpkey, arg);
    233 		if (status < 0)
    234 			goto err;
    235 
    236 		sepol_ibpkey_free(ibpkey);
    237 		ibpkey = NULL;
    238 
    239 		/* Handler requested exit */
    240 		if (status > 0)
    241 			break;
    242 	}
    243 
    244 	return STATUS_SUCCESS;
    245 
    246 err:
    247 	ERR(handle, "could not iterate over ibpkeys");
    248 	sepol_ibpkey_free(ibpkey);
    249 	return STATUS_ERR;
    250 }
    251