• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
node_parse_addr(sepol_handle_t * handle,const char * addr_str,int proto,char * addr_bytes)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 
node_alloc_addr(sepol_handle_t * handle,int proto,char ** addr,size_t * addr_sz)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 
node_expand_addr(sepol_handle_t * handle,char * addr_bytes,int proto,char * addr_str)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 
node_alloc_addr_string(sepol_handle_t * handle,int proto,char ** addr)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 */
sepol_node_key_create(sepol_handle_t * handle,const char * addr,const char * mask,int proto,sepol_node_key_t ** key_ptr)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 
hidden_def(sepol_node_key_create)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 
hidden_def(sepol_node_key_unpack)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 
sepol_node_key_free(sepol_node_key_t * key)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 
hidden_def(sepol_node_key_free)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 
sepol_node_compare2(const sepol_node_t * node,const sepol_node_t * node2)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 */
sepol_node_get_addr(sepol_handle_t * handle,const sepol_node_t * node,char ** 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 
hidden_def(sepol_node_get_addr)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 
hidden_def(sepol_node_get_addr_bytes)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 
hidden_def(sepol_node_set_addr)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 
hidden_def(sepol_node_set_addr_bytes)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 
hidden_def(sepol_node_get_mask)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 
hidden_def(sepol_node_get_mask_bytes)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 
hidden_def(sepol_node_set_mask)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 
hidden_def(sepol_node_set_mask_bytes)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 
hidden_def(sepol_node_get_proto)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 
hidden_def(sepol_node_set_proto)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 
hidden_def(sepol_node_get_proto_str)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 
hidden_def(sepol_node_create)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 */
sepol_node_free(sepol_node_t * node)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 
hidden_def(sepol_node_free)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 
hidden_def(sepol_node_get_con)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