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