diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-12-16 22:04:23 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-12-16 22:04:23 +0000 |
commit | 197ffae2ff2f561cfef790d9fa29aa1a040b71c4 (patch) | |
tree | b51cd2443803ed1956961cdc5feda032ad97b129 /src/nat | |
parent | 7eb418d4f9351657c3722374bd6660f077926eae (diff) | |
download | gnunet-197ffae2ff2f561cfef790d9fa29aa1a040b71c4.tar.gz gnunet-197ffae2ff2f561cfef790d9fa29aa1a040b71c4.zip |
really minimizing code running with root rights
Diffstat (limited to 'src/nat')
-rw-r--r-- | src/nat/gnunet-helper-nat-server-windows.c | 7 | ||||
-rw-r--r-- | src/nat/gnunet-helper-nat-server.c | 153 |
2 files changed, 88 insertions, 72 deletions
diff --git a/src/nat/gnunet-helper-nat-server-windows.c b/src/nat/gnunet-helper-nat-server-windows.c index b15752d8e..d970ffd70 100644 --- a/src/nat/gnunet-helper-nat-server-windows.c +++ b/src/nat/gnunet-helper-nat-server-windows.c | |||
@@ -71,6 +71,11 @@ | |||
71 | #define NAT_TRAV_PORT 22225 | 71 | #define NAT_TRAV_PORT 22225 |
72 | 72 | ||
73 | /** | 73 | /** |
74 | * Must match packet ID used by gnunet-helper-nat-client.c | ||
75 | */ | ||
76 | #define PACKET_ID 256 | ||
77 | |||
78 | /** | ||
74 | * TTL to use for our outgoing messages. | 79 | * TTL to use for our outgoing messages. |
75 | */ | 80 | */ |
76 | #define IPDEFTTL 64 | 81 | #define IPDEFTTL 64 |
@@ -265,7 +270,7 @@ send_icmp_echo (const struct in_addr *my_ip) | |||
265 | ip_pkt.vers_ihl = 0x45; | 270 | ip_pkt.vers_ihl = 0x45; |
266 | ip_pkt.tos = 0; | 271 | ip_pkt.tos = 0; |
267 | ip_pkt.pkt_len = htons (sizeof (packet)); | 272 | ip_pkt.pkt_len = htons (sizeof (packet)); |
268 | ip_pkt.id = htons (256); | 273 | ip_pkt.id = htons (PACKET_ID); |
269 | ip_pkt.flags_frag_offset = 0; | 274 | ip_pkt.flags_frag_offset = 0; |
270 | ip_pkt.ttl = IPDEFTTL; | 275 | ip_pkt.ttl = IPDEFTTL; |
271 | ip_pkt.proto = IPPROTO_ICMP; | 276 | ip_pkt.proto = IPPROTO_ICMP; |
diff --git a/src/nat/gnunet-helper-nat-server.c b/src/nat/gnunet-helper-nat-server.c index e57319d00..40860cb41 100644 --- a/src/nat/gnunet-helper-nat-server.c +++ b/src/nat/gnunet-helper-nat-server.c | |||
@@ -415,64 +415,28 @@ process_icmp_response () | |||
415 | 415 | ||
416 | 416 | ||
417 | /** | 417 | /** |
418 | * Create an ICMP raw socket for reading. | 418 | * Fully initialize the raw socket. |
419 | * | 419 | * |
420 | * @return -1 on error | 420 | * @return -1 on error, 0 on success |
421 | */ | 421 | */ |
422 | static int | 422 | static int |
423 | make_icmp_socket () | 423 | setup_raw_socket () |
424 | { | ||
425 | int ret; | ||
426 | |||
427 | ret = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); | ||
428 | if (-1 == ret) | ||
429 | { | ||
430 | fprintf (stderr, "Error opening RAW socket: %s\n", strerror (errno)); | ||
431 | return -1; | ||
432 | } | ||
433 | if (ret >= FD_SETSIZE) | ||
434 | { | ||
435 | fprintf (stderr, "Socket number too large (%d > %u)\n", ret, | ||
436 | (unsigned int) FD_SETSIZE); | ||
437 | (void) close (ret); | ||
438 | return -1; | ||
439 | } | ||
440 | return ret; | ||
441 | } | ||
442 | |||
443 | |||
444 | /** | ||
445 | * Create an ICMP raw socket for writing. | ||
446 | * | ||
447 | * @return -1 on error | ||
448 | */ | ||
449 | static int | ||
450 | make_raw_socket () | ||
451 | { | 424 | { |
452 | const int one = 1; | 425 | const int one = 1; |
453 | int ret; | ||
454 | 426 | ||
455 | ret = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); | ||
456 | if (-1 == ret) | ||
457 | { | ||
458 | fprintf (stderr, "Error opening RAW socket: %s\n", strerror (errno)); | ||
459 | return -1; | ||
460 | } | ||
461 | if (-1 == | 427 | if (-1 == |
462 | setsockopt (ret, SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof (one))) | 428 | setsockopt (rawsock, SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof (one))) |
463 | { | 429 | { |
464 | fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); | 430 | fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); |
465 | (void) close (ret); | ||
466 | return -1; | 431 | return -1; |
467 | } | 432 | } |
468 | if (-1 == | 433 | if (-1 == |
469 | setsockopt (ret, IPPROTO_IP, IP_HDRINCL, (char *) &one, sizeof (one))) | 434 | setsockopt (rawsock, IPPROTO_IP, IP_HDRINCL, (char *) &one, sizeof (one))) |
470 | { | 435 | { |
471 | fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); | 436 | fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); |
472 | (void) close (ret); | ||
473 | return -1; | 437 | return -1; |
474 | } | 438 | } |
475 | return ret; | 439 | return 0; |
476 | } | 440 | } |
477 | 441 | ||
478 | 442 | ||
@@ -521,56 +485,97 @@ main (int argc, char *const *argv) | |||
521 | struct timeval tv; | 485 | struct timeval tv; |
522 | uid_t uid; | 486 | uid_t uid; |
523 | unsigned int alt; | 487 | unsigned int alt; |
488 | int icmp_eno; | ||
489 | int raw_eno; | ||
490 | int global_ret; | ||
491 | |||
492 | /* Create an ICMP raw socket for reading (we'll check errors later) */ | ||
493 | icmpsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); | ||
494 | icmp_eno = errno; | ||
524 | 495 | ||
496 | /* Create an (ICMP) raw socket for writing (we'll check errors later) */ | ||
497 | rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); | ||
498 | raw_eno = errno; | ||
499 | udpsock = -1; | ||
500 | |||
501 | /* drop root rights */ | ||
502 | uid = getuid (); | ||
503 | #ifdef HAVE_SETRESUID | ||
504 | if (0 != setresuid (uid, uid, uid)) | ||
505 | { | ||
506 | fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); | ||
507 | global_ret = 1; | ||
508 | goto error_exit; | ||
509 | } | ||
510 | #else | ||
511 | if (0 != (setuid (uid) | seteuid (uid))) | ||
512 | { | ||
513 | fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); | ||
514 | global_ret = 2; | ||
515 | goto error_exit; | ||
516 | } | ||
517 | #endif | ||
518 | |||
519 | /* Now that we run without root rights, we can do error checking... */ | ||
525 | if (2 != argc) | 520 | if (2 != argc) |
526 | { | 521 | { |
527 | fprintf (stderr, | 522 | fprintf (stderr, |
528 | "This program must be started with our (internal NAT) IP as the only argument.\n"); | 523 | "This program must be started with our (internal NAT) IP as the only argument.\n"); |
529 | return 1; | 524 | global_ret = 3; |
525 | goto error_exit; | ||
530 | } | 526 | } |
531 | if (1 != inet_pton (AF_INET, argv[1], &external)) | 527 | if (1 != inet_pton (AF_INET, argv[1], &external)) |
532 | { | 528 | { |
533 | fprintf (stderr, "Error parsing IPv4 address: %s\n", strerror (errno)); | 529 | fprintf (stderr, "Error parsing IPv4 address: %s\n", strerror (errno)); |
534 | return 1; | 530 | global_ret = 4; |
531 | goto error_exit; | ||
535 | } | 532 | } |
536 | if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) | 533 | if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) |
537 | { | 534 | { |
538 | fprintf (stderr, "Internal error converting dummy IP to binary.\n"); | 535 | fprintf (stderr, "Internal error converting dummy IP to binary.\n"); |
539 | return 2; | 536 | global_ret = 5; |
537 | goto error_exit; | ||
540 | } | 538 | } |
541 | if (-1 == (icmpsock = make_icmp_socket ())) | 539 | |
540 | /* error checking icmpsock */ | ||
541 | if (-1 == icmpsock) | ||
542 | { | 542 | { |
543 | return 3; | 543 | fprintf (stderr, "Error opening RAW socket: %s\n", strerror (icmp_eno)); |
544 | global_ret = 6; | ||
545 | goto error_exit; | ||
544 | } | 546 | } |
545 | if (-1 == (rawsock = make_raw_socket ())) | 547 | if (icmpsock >= FD_SETSIZE) |
546 | { | 548 | { |
547 | (void) close (icmpsock); | 549 | /* this could happen if we were started with a large number of already-open |
548 | return 4; | 550 | file descriptors... */ |
551 | fprintf (stderr, "Socket number too large (%d > %u)\n", icmpsock, | ||
552 | (unsigned int) FD_SETSIZE); | ||
553 | global_ret = 7; | ||
554 | goto error_exit; | ||
549 | } | 555 | } |
550 | uid = getuid (); | 556 | |
551 | #ifdef HAVE_SETRESUID | 557 | /* error checking rawsock */ |
552 | if (0 != setresuid (uid, uid, uid)) | 558 | if (-1 == rawsock) |
553 | { | 559 | { |
554 | fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); | 560 | fprintf (stderr, "Error opening RAW socket: %s\n", strerror (raw_eno)); |
555 | (void) close (icmpsock); | 561 | global_ret = 8; |
556 | (void) close (rawsock); | 562 | goto error_exit; |
557 | return 5; | ||
558 | } | 563 | } |
559 | #else | 564 | /* no need to check 'rawsock' against FD_SETSIZE as it is never used |
560 | if (0 != (setuid (uid) | seteuid (uid))) | 565 | with 'select' */ |
566 | |||
567 | if (0 != setup_raw_socket ()) | ||
561 | { | 568 | { |
562 | fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); | 569 | global_ret = 9; |
563 | (void) close (icmpsock); | 570 | goto error_exit; |
564 | (void) close (rawsock); | ||
565 | return 6; | ||
566 | } | 571 | } |
567 | #endif | 572 | |
568 | if (-1 == (udpsock = make_udp_socket (&external))) | 573 | if (-1 == (udpsock = make_udp_socket (&external))) |
569 | { | 574 | { |
570 | (void) close (icmpsock); | 575 | global_ret = 10; |
571 | (void) close (rawsock); | 576 | goto error_exit; |
572 | return 7; | ||
573 | } | 577 | } |
578 | |||
574 | alt = 0; | 579 | alt = 0; |
575 | while (1) | 580 | while (1) |
576 | { | 581 | { |
@@ -594,11 +599,17 @@ main (int argc, char *const *argv) | |||
594 | else | 599 | else |
595 | send_udp (); | 600 | send_udp (); |
596 | } | 601 | } |
602 | |||
597 | /* select failed (internal error or OS out of resources) */ | 603 | /* select failed (internal error or OS out of resources) */ |
598 | (void) close (icmpsock); | 604 | global_ret = 11; |
599 | (void) close (rawsock); | 605 | error_exit: |
600 | (void) close (udpsock); | 606 | if (-1 != icmpsock) |
601 | return 8; | 607 | (void) close (icmpsock); |
608 | if (-1 != rawsock) | ||
609 | (void) close (rawsock); | ||
610 | if (-1 != udpsock) | ||
611 | (void) close (udpsock); | ||
612 | return global_ret; | ||
602 | } | 613 | } |
603 | 614 | ||
604 | 615 | ||