aboutsummaryrefslogtreecommitdiff
path: root/src/nat
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-12-16 22:04:23 +0000
committerChristian Grothoff <christian@grothoff.org>2011-12-16 22:04:23 +0000
commit197ffae2ff2f561cfef790d9fa29aa1a040b71c4 (patch)
treeb51cd2443803ed1956961cdc5feda032ad97b129 /src/nat
parent7eb418d4f9351657c3722374bd6660f077926eae (diff)
downloadgnunet-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.c7
-rw-r--r--src/nat/gnunet-helper-nat-server.c153
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 */
422static int 422static int
423make_icmp_socket () 423setup_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 */
449static int
450make_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); 605error_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