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