Home | History | Annotate | Download | only in src
      1 #include <stdlib.h>
      2 #include <stddef.h>
      3 #include <string.h>
      4 #include <netinet/in.h>
      5 #include <arpa/inet.h>
      6 #include <errno.h>
      7 
      8 #include "node_internal.h"
      9 #include "context_internal.h"
     10 #include "debug.h"
     11 
     12 struct sepol_node {
     13 
     14 	/* Network address and mask */
     15 	char *addr;
     16 	size_t addr_sz;
     17 
     18 	char *mask;
     19 	size_t mask_sz;
     20 
     21 	/* Protocol */
     22 	int proto;
     23 
     24 	/* Context */
     25 	sepol_context_t *con;
     26 };
     27 
     28 struct sepol_node_key {
     29 
     30 	/* Network address and mask */
     31 	char *addr;
     32 	size_t addr_sz;
     33 
     34 	char *mask;
     35 	size_t mask_sz;
     36 
     37 	/* Protocol */
     38 	int proto;
     39 };
     40 
     41 /* Converts a string represtation (addr_str)
     42  * to a numeric representation (addr_bytes) */
     43 
     44 static int node_parse_addr(sepol_handle_t * handle,
     45 			   const char *addr_str, int proto, char *addr_bytes)
     46 {
     47 
     48 	switch (proto) {
     49 
     50 	case SEPOL_PROTO_IP4:
     51 		{
     52 			struct in_addr in_addr;
     53 
     54 			if (inet_pton(AF_INET, addr_str, &in_addr) <= 0) {
     55 				ERR(handle, "could not parse IPv4 address "
     56 				    "%s: %s", addr_str, strerror(errno));
     57 				return STATUS_ERR;
     58 			}
     59 
     60 			memcpy(addr_bytes, &in_addr.s_addr, 4);
     61 			break;
     62 		}
     63 	case SEPOL_PROTO_IP6:
     64 		{
     65 			struct in6_addr in_addr;
     66 
     67 			if (inet_pton(AF_INET6, addr_str, &in_addr) <= 0) {
     68 				ERR(handle, "could not parse IPv6 address "
     69 				    "%s: %s", addr_str, strerror(errno));
     70 				return STATUS_ERR;
     71 			}
     72 
     73 #ifdef DARWIN
     74 			memcpy(addr_bytes, in_addr.s6_addr, 16);
     75 #else
     76 			memcpy(addr_bytes, in_addr.s6_addr32, 16);
     77 #endif
     78 			break;
     79 		}
     80 	default:
     81 		ERR(handle, "unsupported protocol %u, could not "
     82 		    "parse address", proto);
     83 		return STATUS_ERR;
     84 	}
     85 
     86 	return STATUS_SUCCESS;
     87 }
     88 
     89 /* Allocates a sufficiently large buffer (addr, addr_sz)
     90  * according the the protocol */
     91 
     92 static int node_alloc_addr(sepol_handle_t * handle,
     93 			   int proto, char **addr, size_t * addr_sz)
     94 {
     95 
     96 	char *tmp_addr = NULL;
     97 	size_t tmp_addr_sz;
     98 
     99 	switch (proto) {
    100 
    101 	case SEPOL_PROTO_IP4:
    102 		tmp_addr_sz = 4;
    103 		tmp_addr = malloc(4);
    104 		if (!tmp_addr)
    105 			goto omem;
    106 		break;
    107 
    108 	case SEPOL_PROTO_IP6:
    109 		tmp_addr_sz = 16;
    110 		tmp_addr = malloc(16);
    111 		if (!tmp_addr)
    112 			goto omem;
    113 		break;
    114 
    115 	default:
    116 		ERR(handle, "unsupported protocol %u", proto);
    117 		goto err;
    118 	}
    119 
    120 	*addr = tmp_addr;
    121 	*addr_sz = tmp_addr_sz;
    122 	return STATUS_SUCCESS;
    123 
    124       omem:
    125 	ERR(handle, "out of memory");
    126 
    127       err:
    128 	free(tmp_addr);
    129 	ERR(handle, "could not allocate address of protocol %s",
    130 	    sepol_node_get_proto_str(proto));
    131 	return STATUS_ERR;
    132 }
    133 
    134 /* Converts a numeric representation (addr_bytes)
    135  * to a string representation (addr_str), according to
    136  * the protocol */
    137 
    138 static int node_expand_addr(sepol_handle_t * handle,
    139 			    char *addr_bytes, int proto, char *addr_str)
    140 {
    141 
    142 	switch (proto) {
    143 
    144 	case SEPOL_PROTO_IP4:
    145 		{
    146 			struct in_addr addr;
    147 			memset(&addr, 0, sizeof(struct in_addr));
    148 			memcpy(&addr.s_addr, addr_bytes, 4);
    149 
    150 			if (inet_ntop(AF_INET, &addr, addr_str,
    151 				      INET_ADDRSTRLEN) == NULL) {
    152 
    153 				ERR(handle,
    154 				    "could not expand IPv4 address to string: %s",
    155 				    strerror(errno));
    156 				return STATUS_ERR;
    157 			}
    158 			break;
    159 		}
    160 
    161 	case SEPOL_PROTO_IP6:
    162 		{
    163 			struct in6_addr addr;
    164 			memset(&addr, 0, sizeof(struct in6_addr));
    165 #ifdef DARWIN
    166 			memcpy(&addr.s6_addr[0], addr_bytes, 16);
    167 #else
    168 			memcpy(&addr.s6_addr32[0], addr_bytes, 16);
    169 #endif
    170 			if (inet_ntop(AF_INET6, &addr, addr_str,
    171 				      INET6_ADDRSTRLEN) == NULL) {
    172 
    173 				ERR(handle,
    174 				    "could not expand IPv6 address to string: %s",
    175 				    strerror(errno));
    176 				return STATUS_ERR;
    177 			}
    178 			break;
    179 		}
    180 
    181 	default:
    182 		ERR(handle, "unsupported protocol %u, could not"
    183 		    " expand address to string", proto);
    184 		return STATUS_ERR;
    185 	}
    186 
    187 	return STATUS_SUCCESS;
    188 }
    189 
    190 /* Allocates a sufficiently large address string (addr)
    191  * according to the protocol */
    192 
    193 static int node_alloc_addr_string(sepol_handle_t * handle,
    194 				  int proto, char **addr)
    195 {
    196 
    197 	char *tmp_addr = NULL;
    198 
    199 	switch (proto) {
    200 
    201 	case SEPOL_PROTO_IP4:
    202 		tmp_addr = malloc(INET_ADDRSTRLEN);
    203 		if (!tmp_addr)
    204 			goto omem;
    205 		break;
    206 
    207 	case SEPOL_PROTO_IP6:
    208 		tmp_addr = malloc(INET6_ADDRSTRLEN);
    209 		if (!tmp_addr)
    210 			goto omem;
    211 		break;
    212 
    213 	default:
    214 		ERR(handle, "unsupported protocol %u", proto);
    215 		goto err;
    216 	}
    217 
    218 	*addr = tmp_addr;
    219 	return STATUS_SUCCESS;
    220 
    221       omem:
    222 	ERR(handle, "out of memory");
    223 
    224       err:
    225 	free(tmp_addr);
    226 	ERR(handle, "could not allocate string buffer for "
    227 	    "address of protocol %s", sepol_node_get_proto_str(proto));
    228 	return STATUS_ERR;
    229 }
    230 
    231 /* Key */
    232 int sepol_node_key_create(sepol_handle_t * handle,
    233 			  const char *addr,
    234 			  const char *mask,
    235 			  int proto, sepol_node_key_t ** key_ptr)
    236 {
    237 
    238 	sepol_node_key_t *tmp_key =
    239 	    (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t));
    240 	if (!tmp_key)
    241 		goto omem;
    242 
    243 	if (node_alloc_addr(handle, proto, &tmp_key->addr, &tmp_key->addr_sz) <
    244 	    0)
    245 		goto err;
    246 	if (node_parse_addr(handle, addr, proto, tmp_key->addr) < 0)
    247 		goto err;
    248 
    249 	if (node_alloc_addr(handle, proto, &tmp_key->mask, &tmp_key->mask_sz) <
    250 	    0)
    251 		goto err;
    252 	if (node_parse_addr(handle, mask, proto, tmp_key->mask) < 0)
    253 		goto err;
    254 
    255 	tmp_key->proto = proto;
    256 
    257 	*key_ptr = tmp_key;
    258 	return STATUS_SUCCESS;
    259 
    260       omem:
    261 	ERR(handle, "out of memory");
    262 
    263       err:
    264 	sepol_node_key_free(tmp_key);
    265 	ERR(handle, "could not create node key for (%s, %s, %s)",
    266 	    addr, mask, sepol_node_get_proto_str(proto));
    267 	return STATUS_ERR;
    268 }
    269 
    270 hidden_def(sepol_node_key_create)
    271 
    272 void sepol_node_key_unpack(const sepol_node_key_t * key,
    273 			   const char **addr, const char **mask, int *proto)
    274 {
    275 
    276 	*addr = key->addr;
    277 	*mask = key->mask;
    278 	*proto = key->proto;
    279 }
    280 
    281 hidden_def(sepol_node_key_unpack)
    282 
    283 int sepol_node_key_extract(sepol_handle_t * handle,
    284 			   const sepol_node_t * node,
    285 			   sepol_node_key_t ** key_ptr)
    286 {
    287 
    288 	sepol_node_key_t *tmp_key =
    289 	    (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t));
    290 	if (!tmp_key)
    291 		goto omem;
    292 
    293 	tmp_key->addr = malloc(node->addr_sz);
    294 	tmp_key->mask = malloc(node->mask_sz);
    295 
    296 	if (!tmp_key->addr || !tmp_key->mask)
    297 		goto omem;
    298 
    299 	memcpy(tmp_key->addr, node->addr, node->addr_sz);
    300 	memcpy(tmp_key->mask, node->mask, node->mask_sz);
    301 	tmp_key->addr_sz = node->addr_sz;
    302 	tmp_key->mask_sz = node->mask_sz;
    303 	tmp_key->proto = node->proto;
    304 
    305 	*key_ptr = tmp_key;
    306 	return STATUS_SUCCESS;
    307 
    308       omem:
    309 	sepol_node_key_free(tmp_key);
    310 	ERR(handle, "out of memory, could not extract node key");
    311 	return STATUS_ERR;
    312 }
    313 
    314 void sepol_node_key_free(sepol_node_key_t * key)
    315 {
    316 
    317 	if (!key)
    318 		return;
    319 
    320 	free(key->addr);
    321 	free(key->mask);
    322 	free(key);
    323 }
    324 
    325 hidden_def(sepol_node_key_free)
    326 
    327 int sepol_node_compare(const sepol_node_t * node, const sepol_node_key_t * key)
    328 {
    329 
    330 	int rc1, rc2;
    331 
    332 	if ((node->addr_sz < key->addr_sz) || (node->mask_sz < key->mask_sz))
    333 		return -1;
    334 
    335 	else if ((node->addr_sz > key->addr_sz) ||
    336 		 (node->mask_sz > key->mask_sz))
    337 		return 1;
    338 
    339 	rc1 = memcmp(node->addr, key->addr, node->addr_sz);
    340 	rc2 = memcmp(node->mask, key->mask, node->mask_sz);
    341 
    342 	return (rc2 != 0) ? rc2 : rc1;
    343 }
    344 
    345 int sepol_node_compare2(const sepol_node_t * node, const sepol_node_t * node2)
    346 {
    347 
    348 	int rc1, rc2;
    349 
    350 	if ((node->addr_sz < node2->addr_sz) ||
    351 	    (node->mask_sz < node2->mask_sz))
    352 		return -1;
    353 
    354 	else if ((node->addr_sz > node2->addr_sz) ||
    355 		 (node->mask_sz > node2->mask_sz))
    356 		return 1;
    357 
    358 	rc1 = memcmp(node->addr, node2->addr, node->addr_sz);
    359 	rc2 = memcmp(node->mask, node2->mask, node->mask_sz);
    360 
    361 	return (rc2 != 0) ? rc2 : rc1;
    362 }
    363 
    364 /* Addr */
    365 int sepol_node_get_addr(sepol_handle_t * handle,
    366 			const sepol_node_t * node, char **addr)
    367 {
    368 
    369 	char *tmp_addr = NULL;
    370 
    371 	if (node_alloc_addr_string(handle, node->proto, &tmp_addr) < 0)
    372 		goto err;
    373 
    374 	if (node_expand_addr(handle, node->addr, node->proto, tmp_addr) < 0)
    375 		goto err;
    376 
    377 	*addr = tmp_addr;
    378 	return STATUS_SUCCESS;
    379 
    380       err:
    381 	free(tmp_addr);
    382 	ERR(handle, "could not get node address");
    383 	return STATUS_ERR;
    384 }
    385 
    386 hidden_def(sepol_node_get_addr)
    387 
    388 int sepol_node_get_addr_bytes(sepol_handle_t * handle,
    389 			      const sepol_node_t * node,
    390 			      char **buffer, size_t * bsize)
    391 {
    392 
    393 	char *tmp_buf = malloc(node->addr_sz);
    394 	if (!tmp_buf) {
    395 		ERR(handle, "out of memory, could not get address bytes");
    396 		return STATUS_ERR;
    397 	}
    398 
    399 	memcpy(tmp_buf, node->addr, node->addr_sz);
    400 	*buffer = tmp_buf;
    401 	*bsize = node->addr_sz;
    402 	return STATUS_SUCCESS;
    403 }
    404 
    405 hidden_def(sepol_node_get_addr_bytes)
    406 
    407 int sepol_node_set_addr(sepol_handle_t * handle,
    408 			sepol_node_t * node, int proto, const char *addr)
    409 {
    410 
    411 	char *tmp_addr = NULL;
    412 	size_t tmp_addr_sz;
    413 
    414 	if (node_alloc_addr(handle, proto, &tmp_addr, &tmp_addr_sz) < 0)
    415 		goto err;
    416 
    417 	if (node_parse_addr(handle, addr, proto, tmp_addr) < 0)
    418 		goto err;
    419 
    420 	free(node->addr);
    421 	node->addr = tmp_addr;
    422 	node->addr_sz = tmp_addr_sz;
    423 	return STATUS_SUCCESS;
    424 
    425       err:
    426 	free(tmp_addr);
    427 	ERR(handle, "could not set node address to %s", addr);
    428 	return STATUS_ERR;
    429 }
    430 
    431 hidden_def(sepol_node_set_addr)
    432 
    433 int sepol_node_set_addr_bytes(sepol_handle_t * handle,
    434 			      sepol_node_t * node,
    435 			      const char *addr, size_t addr_sz)
    436 {
    437 
    438 	char *tmp_addr = malloc(addr_sz);
    439 	if (!tmp_addr) {
    440 		ERR(handle, "out of memory, could not " "set node address");
    441 		return STATUS_ERR;
    442 	}
    443 
    444 	memcpy(tmp_addr, addr, addr_sz);
    445 	free(node->addr);
    446 	node->addr = tmp_addr;
    447 	node->addr_sz = addr_sz;
    448 	return STATUS_SUCCESS;
    449 }
    450 
    451 hidden_def(sepol_node_set_addr_bytes)
    452 
    453 /* Mask */
    454 int sepol_node_get_mask(sepol_handle_t * handle,
    455 			const sepol_node_t * node, char **mask)
    456 {
    457 
    458 	char *tmp_mask = NULL;
    459 
    460 	if (node_alloc_addr_string(handle, node->proto, &tmp_mask) < 0)
    461 		goto err;
    462 
    463 	if (node_expand_addr(handle, node->mask, node->proto, tmp_mask) < 0)
    464 		goto err;
    465 
    466 	*mask = tmp_mask;
    467 	return STATUS_SUCCESS;
    468 
    469       err:
    470 	free(tmp_mask);
    471 	ERR(handle, "could not get node netmask");
    472 	return STATUS_ERR;
    473 }
    474 
    475 hidden_def(sepol_node_get_mask)
    476 
    477 int sepol_node_get_mask_bytes(sepol_handle_t * handle,
    478 			      const sepol_node_t * node,
    479 			      char **buffer, size_t * bsize)
    480 {
    481 
    482 	char *tmp_buf = malloc(node->mask_sz);
    483 	if (!tmp_buf) {
    484 		ERR(handle, "out of memory, could not get netmask bytes");
    485 		return STATUS_ERR;
    486 	}
    487 
    488 	memcpy(tmp_buf, node->mask, node->mask_sz);
    489 	*buffer = tmp_buf;
    490 	*bsize = node->mask_sz;
    491 	return STATUS_SUCCESS;
    492 }
    493 
    494 hidden_def(sepol_node_get_mask_bytes)
    495 
    496 int sepol_node_set_mask(sepol_handle_t * handle,
    497 			sepol_node_t * node, int proto, const char *mask)
    498 {
    499 
    500 	char *tmp_mask = NULL;
    501 	size_t tmp_mask_sz;
    502 
    503 	if (node_alloc_addr(handle, proto, &tmp_mask, &tmp_mask_sz) < 0)
    504 		goto err;
    505 
    506 	if (node_parse_addr(handle, mask, proto, tmp_mask) < 0)
    507 		goto err;
    508 
    509 	free(node->mask);
    510 	node->mask = tmp_mask;
    511 	node->mask_sz = tmp_mask_sz;
    512 	return STATUS_SUCCESS;
    513 
    514       err:
    515 	free(tmp_mask);
    516 	ERR(handle, "could not set node netmask to %s", mask);
    517 	return STATUS_ERR;
    518 }
    519 
    520 hidden_def(sepol_node_set_mask)
    521 
    522 int sepol_node_set_mask_bytes(sepol_handle_t * handle,
    523 			      sepol_node_t * node,
    524 			      const char *mask, size_t mask_sz)
    525 {
    526 
    527 	char *tmp_mask = malloc(mask_sz);
    528 	if (!tmp_mask) {
    529 		ERR(handle, "out of memory, could not " "set node netmask");
    530 		return STATUS_ERR;
    531 	}
    532 	memcpy(tmp_mask, mask, mask_sz);
    533 	free(node->mask);
    534 	node->mask = tmp_mask;
    535 	node->mask_sz = mask_sz;
    536 	return STATUS_SUCCESS;
    537 }
    538 
    539 hidden_def(sepol_node_set_mask_bytes)
    540 
    541 /* Protocol */
    542 int sepol_node_get_proto(const sepol_node_t * node)
    543 {
    544 
    545 	return node->proto;
    546 }
    547 
    548 hidden_def(sepol_node_get_proto)
    549 
    550 void sepol_node_set_proto(sepol_node_t * node, int proto)
    551 {
    552 
    553 	node->proto = proto;
    554 }
    555 
    556 hidden_def(sepol_node_set_proto)
    557 
    558 const char *sepol_node_get_proto_str(int proto)
    559 {
    560 
    561 	switch (proto) {
    562 	case SEPOL_PROTO_IP4:
    563 		return "ipv4";
    564 	case SEPOL_PROTO_IP6:
    565 		return "ipv6";
    566 	default:
    567 		return "???";
    568 	}
    569 }
    570 
    571 hidden_def(sepol_node_get_proto_str)
    572 
    573 /* Create */
    574 int sepol_node_create(sepol_handle_t * handle, sepol_node_t ** node)
    575 {
    576 
    577 	sepol_node_t *tmp_node = (sepol_node_t *) malloc(sizeof(sepol_node_t));
    578 
    579 	if (!tmp_node) {
    580 		ERR(handle, "out of memory, could not create " "node record");
    581 		return STATUS_ERR;
    582 	}
    583 
    584 	tmp_node->addr = NULL;
    585 	tmp_node->addr_sz = 0;
    586 	tmp_node->mask = NULL;
    587 	tmp_node->mask_sz = 0;
    588 	tmp_node->proto = SEPOL_PROTO_IP4;
    589 	tmp_node->con = NULL;
    590 	*node = tmp_node;
    591 
    592 	return STATUS_SUCCESS;
    593 }
    594 
    595 hidden_def(sepol_node_create)
    596 
    597 /* Deep copy clone */
    598 int sepol_node_clone(sepol_handle_t * handle,
    599 		     const sepol_node_t * node, sepol_node_t ** node_ptr)
    600 {
    601 
    602 	sepol_node_t *new_node = NULL;
    603 	if (sepol_node_create(handle, &new_node) < 0)
    604 		goto err;
    605 
    606 	/* Copy address, mask, protocol */
    607 	new_node->addr = malloc(node->addr_sz);
    608 	new_node->mask = malloc(node->mask_sz);
    609 	if (!new_node->addr || !new_node->mask)
    610 		goto omem;
    611 
    612 	memcpy(new_node->addr, node->addr, node->addr_sz);
    613 	memcpy(new_node->mask, node->mask, node->mask_sz);
    614 	new_node->addr_sz = node->addr_sz;
    615 	new_node->mask_sz = node->mask_sz;
    616 	new_node->proto = node->proto;
    617 
    618 	/* Copy context */
    619 	if (node->con &&
    620 	    (sepol_context_clone(handle, node->con, &new_node->con) < 0))
    621 		goto err;
    622 
    623 	*node_ptr = new_node;
    624 	return STATUS_SUCCESS;
    625 
    626       omem:
    627 	ERR(handle, "out of memory");
    628 
    629       err:
    630 	ERR(handle, "could not clone node record");
    631 	sepol_node_free(new_node);
    632 	return STATUS_ERR;
    633 }
    634 
    635 /* Destroy */
    636 void sepol_node_free(sepol_node_t * node)
    637 {
    638 
    639 	if (!node)
    640 		return;
    641 
    642 	sepol_context_free(node->con);
    643 	free(node->addr);
    644 	free(node->mask);
    645 	free(node);
    646 }
    647 
    648 hidden_def(sepol_node_free)
    649 
    650 /* Context */
    651 sepol_context_t *sepol_node_get_con(const sepol_node_t * node)
    652 {
    653 
    654 	return node->con;
    655 }
    656 
    657 hidden_def(sepol_node_get_con)
    658 
    659 int sepol_node_set_con(sepol_handle_t * handle,
    660 		       sepol_node_t * node, sepol_context_t * con)
    661 {
    662 
    663 	sepol_context_t *newcon;
    664 
    665 	if (sepol_context_clone(handle, con, &newcon) < 0) {
    666 		ERR(handle, "out of memory, could not set node context");
    667 		return STATUS_ERR;
    668 	}
    669 
    670 	sepol_context_free(node->con);
    671 	node->con = newcon;
    672 	return STATUS_SUCCESS;
    673 }
    674 
    675 hidden_def(sepol_node_set_con)
    676