aboutsummaryrefslogtreecommitdiff
path: root/src/nat/gnunet-helper-nat-client.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-12-16 22:13:31 +0000
committerChristian Grothoff <christian@grothoff.org>2011-12-16 22:13:31 +0000
commit3b86b5c67188a7a585869d05573c47a4903bbd00 (patch)
tree8ccb97836139a8624d57e16ca4d174c990d991ff /src/nat/gnunet-helper-nat-client.c
parent197ffae2ff2f561cfef790d9fa29aa1a040b71c4 (diff)
downloadgnunet-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.c101
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/** 409int
410 * Create an ICMP raw socket for writing. 410main (int argc, char *const *argv)
411 *
412 * @return -1 on error
413 */
414static int
415make_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
444int
445main (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