diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-12-16 22:13:31 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-12-16 22:13:31 +0000 |
commit | 3b86b5c67188a7a585869d05573c47a4903bbd00 (patch) | |
tree | 8ccb97836139a8624d57e16ca4d174c990d991ff /src/nat/gnunet-helper-nat-client.c | |
parent | 197ffae2ff2f561cfef790d9fa29aa1a040b71c4 (diff) | |
download | gnunet-3b86b5c67188a7a585869d05573c47a4903bbd00.tar.gz gnunet-3b86b5c67188a7a585869d05573c47a4903bbd00.zip |
really minimizing gnunet-helper-nat-client code running with root rights
Diffstat (limited to 'src/nat/gnunet-helper-nat-client.c')
-rw-r--r-- | src/nat/gnunet-helper-nat-client.c | 101 |
1 files changed, 51 insertions, 50 deletions
diff --git a/src/nat/gnunet-helper-nat-client.c b/src/nat/gnunet-helper-nat-client.c index 579090fe2..3f74c22c2 100644 --- a/src/nat/gnunet-helper-nat-client.c +++ b/src/nat/gnunet-helper-nat-client.c | |||
@@ -406,91 +406,92 @@ send_icmp (const struct in_addr *my_ip, const struct in_addr *other) | |||
406 | } | 406 | } |
407 | 407 | ||
408 | 408 | ||
409 | /** | 409 | int |
410 | * Create an ICMP raw socket for writing. | 410 | main (int argc, char *const *argv) |
411 | * | ||
412 | * @return -1 on error | ||
413 | */ | ||
414 | static int | ||
415 | make_raw_socket () | ||
416 | { | 411 | { |
417 | const int one = 1; | 412 | const int one = 1; |
418 | int ret; | 413 | struct in_addr external; |
414 | struct in_addr target; | ||
415 | uid_t uid; | ||
416 | unsigned int p; | ||
417 | int raw_eno; | ||
418 | int global_ret; | ||
419 | 419 | ||
420 | ret = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); | 420 | /* Create an ICMP raw socket for writing (only operation that requires root) */ |
421 | if (-1 == ret) | 421 | rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); |
422 | raw_eno = errno; /* for later error checking */ | ||
423 | |||
424 | /* now drop root privileges */ | ||
425 | uid = getuid (); | ||
426 | #ifdef HAVE_SETRESUID | ||
427 | if (0 != setresuid (uid, uid, uid)) | ||
428 | { | ||
429 | fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); | ||
430 | global_ret = 1; | ||
431 | goto cleanup; | ||
432 | } | ||
433 | #else | ||
434 | if (0 != (setuid (uid) | seteuid (uid))) | ||
435 | { | ||
436 | fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); | ||
437 | global_ret = 2; | ||
438 | goto cleanup; | ||
439 | } | ||
440 | #endif | ||
441 | if (-1 == rawsock) | ||
422 | { | 442 | { |
423 | fprintf (stderr, "Error opening RAW socket: %s\n", strerror (errno)); | 443 | fprintf (stderr, "Error opening RAW socket: %s\n", strerror (raw_eno)); |
424 | return -1; | 444 | global_ret = 3; |
445 | goto cleanup; | ||
425 | } | 446 | } |
426 | if (0 != | 447 | if (0 != |
427 | setsockopt (ret, SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof (one))) | 448 | setsockopt (rawsock, SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof (one))) |
428 | { | 449 | { |
429 | fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); | 450 | fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); |
430 | (void) close (ret); | 451 | global_ret = 4; |
431 | return -1; | 452 | goto cleanup; |
432 | } | 453 | } |
433 | if (0 != | 454 | if (0 != |
434 | setsockopt (ret, IPPROTO_IP, IP_HDRINCL, (char *) &one, sizeof (one))) | 455 | setsockopt (rawsock, IPPROTO_IP, IP_HDRINCL, (char *) &one, sizeof (one))) |
435 | { | 456 | { |
436 | fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); | 457 | fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); |
437 | (void) close (ret); | 458 | global_ret = 5; |
438 | return -1; | 459 | goto cleanup; |
439 | } | 460 | } |
440 | return ret; | ||
441 | } | ||
442 | |||
443 | |||
444 | int | ||
445 | main (int argc, char *const *argv) | ||
446 | { | ||
447 | struct in_addr external; | ||
448 | struct in_addr target; | ||
449 | uid_t uid; | ||
450 | unsigned int p; | ||
451 | 461 | ||
452 | if (4 != argc) | 462 | if (4 != argc) |
453 | { | 463 | { |
454 | fprintf (stderr, | 464 | fprintf (stderr, |
455 | "This program must be started with our IP, the targets external IP, and our port as arguments.\n"); | 465 | "This program must be started with our IP, the targets external IP, and our port as arguments.\n"); |
456 | return 1; | 466 | global_ret = 6; |
467 | goto cleanup; | ||
457 | } | 468 | } |
458 | if ((1 != inet_pton (AF_INET, argv[1], &external)) || | 469 | if ((1 != inet_pton (AF_INET, argv[1], &external)) || |
459 | (1 != inet_pton (AF_INET, argv[2], &target))) | 470 | (1 != inet_pton (AF_INET, argv[2], &target))) |
460 | { | 471 | { |
461 | fprintf (stderr, "Error parsing IPv4 address: %s\n", strerror (errno)); | 472 | fprintf (stderr, "Error parsing IPv4 address: %s\n", strerror (errno)); |
462 | return 1; | 473 | global_ret = 7; |
474 | goto cleanup; | ||
463 | } | 475 | } |
464 | if ((1 != sscanf (argv[3], "%u", &p)) || (0 == p) || (0xFFFF < p)) | 476 | if ((1 != sscanf (argv[3], "%u", &p)) || (0 == p) || (0xFFFF < p)) |
465 | { | 477 | { |
466 | fprintf (stderr, "Error parsing port value `%s'\n", argv[3]); | 478 | fprintf (stderr, "Error parsing port value `%s'\n", argv[3]); |
467 | return 1; | 479 | global_ret = 8; |
480 | goto cleanup; | ||
468 | } | 481 | } |
469 | port = (uint16_t) p; | 482 | port = (uint16_t) p; |
470 | if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) | 483 | if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) |
471 | { | 484 | { |
472 | fprintf (stderr, "Internal error converting dummy IP to binary.\n"); | 485 | fprintf (stderr, "Internal error converting dummy IP to binary.\n"); |
473 | return 2; | 486 | global_ret = 9; |
474 | } | 487 | goto cleanup; |
475 | if (-1 == (rawsock = make_raw_socket ())) | ||
476 | return 2; | ||
477 | uid = getuid (); | ||
478 | #ifdef HAVE_SETRESUID | ||
479 | if (0 != setresuid (uid, uid, uid)) | ||
480 | { | ||
481 | fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); | ||
482 | return 3; | ||
483 | } | 488 | } |
484 | #else | ||
485 | if (0 != (setuid (uid) | seteuid (uid))) | ||
486 | { | ||
487 | fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); | ||
488 | return 6; | ||
489 | } | ||
490 | #endif | ||
491 | send_icmp (&external, &target); | 489 | send_icmp (&external, &target); |
492 | send_icmp_udp (&external, &target); | 490 | send_icmp_udp (&external, &target); |
493 | (void) close (rawsock); | 491 | global_ret = 0; |
492 | cleanup: | ||
493 | if (-1 != rawsock) | ||
494 | (void) close (rawsock); | ||
494 | return 0; | 495 | return 0; |
495 | } | 496 | } |
496 | 497 | ||