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 to 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