Home | History | Annotate | Download | only in src
      1 #include <netinet/in.h>
      2 #include <arpa/inet.h>
      3 #include <stdlib.h>
      4 
      5 #include "debug.h"
      6 #include "context.h"
      7 #include "handle.h"
      8 
      9 #include <sepol/policydb/policydb.h>
     10 #include "node_internal.h"
     11 
     12 /* Create a low level node structure from
     13  * a high level representation */
     14 static int node_from_record(sepol_handle_t * handle,
     15 			    const policydb_t * policydb,
     16 			    ocontext_t ** node, const sepol_node_t * data)
     17 {
     18 
     19 	ocontext_t *tmp_node = NULL;
     20 	context_struct_t *tmp_con = NULL;
     21 	char *addr_buf = NULL, *mask_buf = NULL;
     22 
     23 	tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t));
     24 	if (!tmp_node)
     25 		goto omem;
     26 
     27 	size_t addr_bsize, mask_bsize;
     28 
     29 	/* Address and netmask */
     30 	if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0)
     31 		goto err;
     32 	if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0)
     33 		goto err;
     34 
     35 	int proto = sepol_node_get_proto(data);
     36 
     37 	switch (proto) {
     38 	case SEPOL_PROTO_IP4:
     39 		memcpy(&tmp_node->u.node.addr, addr_buf, addr_bsize);
     40 		memcpy(&tmp_node->u.node.mask, mask_buf, mask_bsize);
     41 		break;
     42 	case SEPOL_PROTO_IP6:
     43 		memcpy(tmp_node->u.node6.addr, addr_buf, addr_bsize);
     44 		memcpy(tmp_node->u.node6.mask, mask_buf, mask_bsize);
     45 		break;
     46 	default:
     47 		ERR(handle, "unsupported protocol %u", proto);
     48 		goto err;
     49 	}
     50 	free(addr_buf);
     51 	free(mask_buf);
     52 	addr_buf = NULL;
     53 	mask_buf = NULL;
     54 
     55 	/* Context */
     56 	if (context_from_record(handle, policydb, &tmp_con,
     57 				sepol_node_get_con(data)) < 0)
     58 		goto err;
     59 	context_cpy(&tmp_node->context[0], tmp_con);
     60 	context_destroy(tmp_con);
     61 	free(tmp_con);
     62 	tmp_con = NULL;
     63 
     64 	*node = tmp_node;
     65 	return STATUS_SUCCESS;
     66 
     67       omem:
     68 	ERR(handle, "out of memory");
     69 
     70       err:
     71 	if (tmp_node != NULL) {
     72 		context_destroy(&tmp_node->context[0]);
     73 		free(tmp_node);
     74 	}
     75 	context_destroy(tmp_con);
     76 	free(tmp_con);
     77 	free(addr_buf);
     78 	free(mask_buf);
     79 	ERR(handle, "could not create node structure");
     80 	return STATUS_ERR;
     81 }
     82 
     83 static int node_to_record(sepol_handle_t * handle,
     84 			  const policydb_t * policydb,
     85 			  ocontext_t * node, int proto, sepol_node_t ** record)
     86 {
     87 
     88 	context_struct_t *con = &node->context[0];
     89 
     90 	sepol_context_t *tmp_con = NULL;
     91 	sepol_node_t *tmp_record = NULL;
     92 
     93 	if (sepol_node_create(handle, &tmp_record) < 0)
     94 		goto err;
     95 
     96 	sepol_node_set_proto(tmp_record, proto);
     97 
     98 	switch (proto) {
     99 
    100 	case SEPOL_PROTO_IP4:
    101 		if (sepol_node_set_addr_bytes(handle, tmp_record,
    102 					      (const char *)&node->u.node.addr,
    103 					      4) < 0)
    104 			goto err;
    105 
    106 		if (sepol_node_set_mask_bytes(handle, tmp_record,
    107 					      (const char *)&node->u.node.mask,
    108 					      4) < 0)
    109 			goto err;
    110 		break;
    111 
    112 	case SEPOL_PROTO_IP6:
    113 		if (sepol_node_set_addr_bytes(handle, tmp_record,
    114 					      (const char *)&node->u.node6.addr,
    115 					      16) < 0)
    116 			goto err;
    117 
    118 		if (sepol_node_set_mask_bytes(handle, tmp_record,
    119 					      (const char *)&node->u.node6.mask,
    120 					      16) < 0)
    121 			goto err;
    122 		break;
    123 
    124 	default:
    125 		ERR(handle, "unsupported protocol %u", proto);
    126 		goto err;
    127 	}
    128 
    129 	if (context_to_record(handle, policydb, con, &tmp_con) < 0)
    130 		goto err;
    131 
    132 	if (sepol_node_set_con(handle, tmp_record, tmp_con) < 0)
    133 		goto err;
    134 
    135 	sepol_context_free(tmp_con);
    136 	*record = tmp_record;
    137 	return STATUS_SUCCESS;
    138 
    139       err:
    140 	ERR(handle, "could not convert node to record");
    141 	sepol_context_free(tmp_con);
    142 	sepol_node_free(tmp_record);
    143 	return STATUS_ERR;
    144 }
    145 
    146 /* Return the number of nodes */
    147 extern int sepol_node_count(sepol_handle_t * handle __attribute__ ((unused)),
    148 			    const sepol_policydb_t * p, unsigned int *response)
    149 {
    150 
    151 	unsigned int count = 0;
    152 	ocontext_t *c, *head;
    153 	const policydb_t *policydb = &p->p;
    154 
    155 	head = policydb->ocontexts[OCON_NODE];
    156 	for (c = head; c != NULL; c = c->next)
    157 		count++;
    158 
    159 	head = policydb->ocontexts[OCON_NODE6];
    160 	for (c = head; c != NULL; c = c->next)
    161 		count++;
    162 
    163 	*response = count;
    164 
    165 	return STATUS_SUCCESS;
    166 }
    167 
    168 /* Check if a node exists */
    169 int sepol_node_exists(sepol_handle_t * handle,
    170 		      const sepol_policydb_t * p,
    171 		      const sepol_node_key_t * key, int *response)
    172 {
    173 
    174 	const policydb_t *policydb = &p->p;
    175 	ocontext_t *c, *head;
    176 
    177 	int proto;
    178 	const char *addr, *mask;
    179 	sepol_node_key_unpack(key, &addr, &mask, &proto);
    180 
    181 	switch (proto) {
    182 
    183 	case SEPOL_PROTO_IP4:
    184 		{
    185 			head = policydb->ocontexts[OCON_NODE];
    186 			for (c = head; c; c = c->next) {
    187 				unsigned int *addr2 = &c->u.node.addr;
    188 				unsigned int *mask2 = &c->u.node.mask;
    189 
    190 				if (!memcmp(addr, addr2, 4) &&
    191 				    !memcmp(mask, mask2, 4)) {
    192 
    193 					*response = 1;
    194 					return STATUS_SUCCESS;
    195 				}
    196 			}
    197 			break;
    198 		}
    199 	case SEPOL_PROTO_IP6:
    200 		{
    201 			head = policydb->ocontexts[OCON_NODE6];
    202 			for (c = head; c; c = c->next) {
    203 				unsigned int *addr2 = c->u.node6.addr;
    204 				unsigned int *mask2 = c->u.node6.mask;
    205 
    206 				if (!memcmp(addr, addr2, 16) &&
    207 				    !memcmp(mask, mask2, 16)) {
    208 					*response = 1;
    209 					return STATUS_SUCCESS;
    210 				}
    211 			}
    212 			break;
    213 		}
    214 	default:
    215 		ERR(handle, "unsupported protocol %u", proto);
    216 		goto err;
    217 	}
    218 
    219 	*response = 0;
    220 	return STATUS_SUCCESS;
    221 
    222       err:
    223 	ERR(handle, "could not check if node %s/%s (%s) exists",
    224 	    addr, mask, sepol_node_get_proto_str(proto));
    225 	return STATUS_ERR;
    226 }
    227 
    228 /* Query a node */
    229 int sepol_node_query(sepol_handle_t * handle,
    230 		     const sepol_policydb_t * p,
    231 		     const sepol_node_key_t * key, sepol_node_t ** response)
    232 {
    233 
    234 	const policydb_t *policydb = &p->p;
    235 	ocontext_t *c, *head;
    236 
    237 	int proto;
    238 	const char *addr, *mask;
    239 	sepol_node_key_unpack(key, &addr, &mask, &proto);
    240 
    241 	switch (proto) {
    242 
    243 	case SEPOL_PROTO_IP4:
    244 		{
    245 			head = policydb->ocontexts[OCON_NODE];
    246 			for (c = head; c; c = c->next) {
    247 				unsigned int *addr2 = &c->u.node.addr;
    248 				unsigned int *mask2 = &c->u.node.mask;
    249 
    250 				if (!memcmp(addr, addr2, 4) &&
    251 				    !memcmp(mask, mask2, 4)) {
    252 
    253 					if (node_to_record(handle, policydb,
    254 							   c, SEPOL_PROTO_IP4,
    255 							   response) < 0)
    256 						goto err;
    257 					return STATUS_SUCCESS;
    258 				}
    259 			}
    260 			break;
    261 		}
    262 	case SEPOL_PROTO_IP6:
    263 		{
    264 			head = policydb->ocontexts[OCON_NODE6];
    265 			for (c = head; c; c = c->next) {
    266 				unsigned int *addr2 = c->u.node6.addr;
    267 				unsigned int *mask2 = c->u.node6.mask;
    268 
    269 				if (!memcmp(addr, addr2, 16) &&
    270 				    !memcmp(mask, mask2, 16)) {
    271 
    272 					if (node_to_record(handle, policydb,
    273 							   c, SEPOL_PROTO_IP6,
    274 							   response) < 0)
    275 						goto err;
    276 					return STATUS_SUCCESS;
    277 				}
    278 			}
    279 			break;
    280 		}
    281 	default:
    282 		ERR(handle, "unsupported protocol %u", proto);
    283 		goto err;
    284 	}
    285 	*response = NULL;
    286 	return STATUS_SUCCESS;
    287 
    288       err:
    289 	ERR(handle, "could not query node %s/%s (%s)",
    290 	    addr, mask, sepol_node_get_proto_str(proto));
    291 	return STATUS_ERR;
    292 
    293 }
    294 
    295 /* Load a node into policy */
    296 int sepol_node_modify(sepol_handle_t * handle,
    297 		      sepol_policydb_t * p,
    298 		      const sepol_node_key_t * key, const sepol_node_t * data)
    299 {
    300 
    301 	policydb_t *policydb = &p->p;
    302 	ocontext_t *node = NULL;
    303 
    304 	int proto;
    305 	const char *addr, *mask;
    306 
    307 	sepol_node_key_unpack(key, &addr, &mask, &proto);
    308 
    309 	if (node_from_record(handle, policydb, &node, data) < 0)
    310 		goto err;
    311 
    312 	switch (proto) {
    313 
    314 	case SEPOL_PROTO_IP4:
    315 		{
    316 			/* Attach to context list */
    317 			node->next = policydb->ocontexts[OCON_NODE];
    318 			policydb->ocontexts[OCON_NODE] = node;
    319 			break;
    320 		}
    321 	case SEPOL_PROTO_IP6:
    322 		{
    323 			/* Attach to context list */
    324 			node->next = policydb->ocontexts[OCON_NODE6];
    325 			policydb->ocontexts[OCON_NODE6] = node;
    326 			break;
    327 		}
    328 	default:
    329 		ERR(handle, "unsupported protocol %u", proto);
    330 		goto err;
    331 	}
    332 
    333 	return STATUS_SUCCESS;
    334 
    335       err:
    336 	ERR(handle, "could not load node %s/%s (%s)",
    337 	    addr, mask, sepol_node_get_proto_str(proto));
    338 	if (node != NULL) {
    339 		context_destroy(&node->context[0]);
    340 		free(node);
    341 	}
    342 	return STATUS_ERR;
    343 }
    344 
    345 int sepol_node_iterate(sepol_handle_t * handle,
    346 		       const sepol_policydb_t * p,
    347 		       int (*fn) (const sepol_node_t * node,
    348 				  void *fn_arg), void *arg)
    349 {
    350 
    351 	const policydb_t *policydb = &p->p;
    352 	ocontext_t *c, *head;
    353 	sepol_node_t *node = NULL;
    354 	int status;
    355 
    356 	head = policydb->ocontexts[OCON_NODE];
    357 	for (c = head; c; c = c->next) {
    358 		if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP4, &node)
    359 		    < 0)
    360 			goto err;
    361 
    362 		/* Invoke handler */
    363 		status = fn(node, arg);
    364 		if (status < 0)
    365 			goto err;
    366 
    367 		sepol_node_free(node);
    368 		node = NULL;
    369 
    370 		/* Handler requested exit */
    371 		if (status > 0)
    372 			break;
    373 	}
    374 
    375 	head = policydb->ocontexts[OCON_NODE6];
    376 	for (c = head; c; c = c->next) {
    377 		if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP6, &node)
    378 		    < 0)
    379 			goto err;
    380 
    381 		/* Invoke handler */
    382 		status = fn(node, arg);
    383 		if (status < 0)
    384 			goto err;
    385 
    386 		sepol_node_free(node);
    387 		node = NULL;
    388 
    389 		/* Handler requested exit */
    390 		if (status > 0)
    391 			break;
    392 	}
    393 
    394 	return STATUS_SUCCESS;
    395 
    396       err:
    397 	ERR(handle, "could not iterate over nodes");
    398 	sepol_node_free(node);
    399 	return STATUS_ERR;
    400 }
    401