gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r19722 - gnunet/src/dns


From: gnunet
Subject: [GNUnet-SVN] r19722 - gnunet/src/dns
Date: Tue, 7 Feb 2012 17:24:08 +0100

Author: grothoff
Date: 2012-02-07 17:24:08 +0100 (Tue, 07 Feb 2012)
New Revision: 19722

Modified:
   gnunet/src/dns/gnunet-helper-dns.c
   gnunet/src/dns/gnunet-service-dns.c
Log:
-updating DNS code to use GID match instead of source port match, introduce 
source port randomization

Modified: gnunet/src/dns/gnunet-helper-dns.c
===================================================================
--- gnunet/src/dns/gnunet-helper-dns.c  2012-02-07 15:59:51 UTC (rev 19721)
+++ gnunet/src/dns/gnunet-helper-dns.c  2012-02-07 16:24:08 UTC (rev 19722)
@@ -35,7 +35,9 @@
  * administrators must take care to not cause conflicts with these
  * values (it was deemed safest to hardcode them as passing these
  * values as arguments might permit messing with arbitrary firewall
- * rules, which would be dangerous).
+ * rules, which would be dangerous).  Traffic coming from the same
+ * group ID as the effective group ID that this process is running
+ * as is not intercepted.
  *
  * The code first sets up the virtual interface, then begins to
  * redirect the DNS traffic to it, and then on errors or SIGTERM shuts
@@ -659,7 +661,6 @@
  *             3: IPv6 netmask length in bits ("64")
  *             4: IPv4 address for the tunnel ("1.2.3.4")
  *             5: IPv4 netmask ("255.255.0.0")
- *             6: PORT to not hijack ("55533")
  * @return 0 on success, otherwise code indicating type of error:
  *         1 wrong number of arguments
  *         2 invalid arguments (i.e. port number / prefix length wrong)
@@ -678,13 +679,12 @@
 int
 main (int argc, char *const*argv)
 {
-  unsigned int port;
-  char localport[6];
   int r;
   char dev[IFNAMSIZ];
+  char mygid[32];
   int fd_tun;
 
-  if (7 != argc)
+  if (6 != argc)
   {
     fprintf (stderr, "Fatal: must supply 6 arguments!\n");
     return 1;
@@ -714,20 +714,8 @@
     return 4;
   }
 
-  /* validate port number */
-  port = atoi (argv[6]);
-  if ( (port == 0) || (port >= 65536) )
-  {
-    fprintf (stderr, 
-            "Port `%u' is invalid\n",
-            port);
-    return 2;
-  }
-  /* print port number to string for command-line use*/
-  (void) snprintf (localport,
-                  sizeof (localport), 
-                  "%u", 
-                  port);
+  /* setup 'mygid' string */
+  snprintf (mygid, sizeof (mygid), "%d", (int) getegid());
 
   /* do not die on SIGPIPE */
   if (SIG_ERR == signal (SIGPIPE, SIG_IGN))
@@ -827,14 +815,15 @@
   }
   
   /* update routing tables -- next part why we need SUID! */
-  /* Forward everything from the given local port (with destination
-     to port 53, and only for UDP) without hijacking */
+  /* Forward everything from our EGID (which should only be held
+     by the 'gnunet-service-dns') and with destination
+     to port 53 on UDP, without hijacking */
   r = 8; /* failed to fully setup routing table */
   {
     char *const mangle_args[] = 
       {
-       "iptables", "-t", "mangle", "-I", "OUTPUT", "1", "-p",
-       "udp", "--sport", localport, "--dport", DNS_PORT, "-j",
+       "iptables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p",
+       "udp", "!", "--gid-owner", mygid, "--dport", DNS_PORT, "-j",
        "ACCEPT", NULL
       };
     if (0 != fork_and_exec (sbin_iptables, mangle_args))
@@ -948,8 +937,8 @@
   {
     char *const mangle_clean_args[] =
       {
-       "iptables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp",
-       "--sport", localport, "--dport", DNS_PORT, "-j", "ACCEPT",
+       "iptables", "-m", "owner", "-t", "mangle", "-D", "OUTPUT", "-p", "udp",
+       "!", "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT",
        NULL
       };
     if (0 != fork_and_exec (sbin_iptables, mangle_clean_args))

Modified: gnunet/src/dns/gnunet-service-dns.c
===================================================================
--- gnunet/src/dns/gnunet-service-dns.c 2012-02-07 15:59:51 UTC (rev 19721)
+++ gnunet/src/dns/gnunet-service-dns.c 2012-02-07 16:24:08 UTC (rev 19722)
@@ -164,7 +164,6 @@
 };
 
 
-
 /**
  * State we keep for each DNS tunnel that terminates at this node.
  */
@@ -236,12 +235,6 @@
 static GNUNET_SCHEDULER_TaskIdentifier read6_task;
 
 /**
- * The port bound to the socket dnsout (and/or dnsout6).  We always (try) to 
bind
- * both sockets to the same port.
- */
-static uint16_t dnsoutport;
-
-/**
  * The configuration to use
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -259,7 +252,7 @@
 /**
  * Command-line arguments we are giving to the hijacker process.
  */
-static char *helper_argv[8];
+static char *helper_argv[7];
 
 /**
  * Head of DLL of clients we consult.
@@ -303,7 +296,12 @@
  */
 static struct GNUNET_MESH_Handle *mesh;
 
+/**
+ * Number of active DNS requests.
+ */
+static unsigned int dns_active;
 
+
 /**
  * We're done processing a DNS request, free associated memory.
  *
@@ -335,7 +333,7 @@
 
   GNUNET_HELPER_stop (hijacker);
   hijacker = NULL;
-  for (i=0;i<8;i++)
+  for (i=0;i<7;i++)
     GNUNET_free_non_null (helper_argv[i]);
   if (NULL != dnsout4)
   {
@@ -561,6 +559,13 @@
 
 
 /**
+ * Try to change the source ports we are bound to.
+ */
+static void
+change_source_ports ();
+
+
+/**
  * A client has completed its processing for this
  * request.  Move on.
  *
@@ -621,6 +626,7 @@
     return;
   case RP_QUERY:
     rr->phase = RP_INTERNET_DNS;
+    dns_active++;
     switch (rr->dst_addr.ss_family)
     {
     case AF_INET:
@@ -651,6 +657,9 @@
                                  salen);
     return;
   case RP_INTERNET_DNS:
+    dns_active--;
+    if (0 == dns_active)
+      change_source_ports ();
     rr->phase = RP_MODIFY;
     for (cr = clients_head; NULL != cr; cr = cr->next)
     {
@@ -904,7 +913,6 @@
 open_port4 ()
 {
   struct sockaddr_in addr;
-  socklen_t addrlen;
 
   dnsout4 = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0);
   if (dnsout4 == NULL)
@@ -925,25 +933,6 @@
     dnsout4 = NULL;
     return GNUNET_SYSERR;
   }
-
-  /* Read the port we bound to */
-  addrlen = sizeof (struct sockaddr_in);
-  if (0 != getsockname (GNUNET_NETWORK_get_fd (dnsout4), 
-                       (struct sockaddr *) &addr,
-                       &addrlen))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-               _("Could not determine port I got: %s\n"),
-               STRERROR (errno));
-    GNUNET_NETWORK_socket_close (dnsout4);
-    dnsout4 = NULL;
-    return GNUNET_SYSERR;
-  }
-  dnsoutport = htons (addr.sin_port);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
-             _("GNUnet DNS will exit on source port %u\n"),
-             (unsigned int) dnsoutport);
   read4_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, 
                                              dnsout4,
                                              &read_response, dnsout4);
@@ -961,7 +950,6 @@
 open_port6 ()
 {
   struct sockaddr_in6 addr;
-  socklen_t addrlen;
 
   dnsout6 = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_DGRAM, 0);
   if (dnsout6 == NULL)
@@ -973,7 +961,6 @@
   }
   memset (&addr, 0, sizeof (struct sockaddr_in6));
   addr.sin6_family = AF_INET6;
-  addr.sin6_port = htons (dnsoutport);
   int err = GNUNET_NETWORK_socket_bind (dnsout6,
                                         (struct sockaddr *) &addr,
                                         sizeof (struct sockaddr_in6));
@@ -981,29 +968,12 @@
   if (err != GNUNET_OK)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               _("Could not bind to port %u: %s\n"),
-               (unsigned int) dnsoutport,
+               _("Could not bind: %s\n"),
                STRERROR (errno));
     GNUNET_NETWORK_socket_close (dnsout6);
     dnsout6 = NULL;
     return GNUNET_SYSERR;
   }
-  if (0 == dnsoutport)
-  {
-    addrlen = sizeof (struct sockaddr_in6);
-    if (0 != getsockname (GNUNET_NETWORK_get_fd (dnsout6), 
-                         (struct sockaddr *) &addr,
-                         &addrlen))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
-                 _("Could not determine port I got: %s\n"),
-                 STRERROR (errno));
-      GNUNET_NETWORK_socket_close (dnsout6);
-      dnsout6 = NULL;
-      return GNUNET_SYSERR;
-    }
-  }
-  dnsoutport = htons (addr.sin6_port);
   read6_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                              dnsout6,
                                              &read_response, dnsout6);
@@ -1012,6 +982,54 @@
 
 
 /**
+ * Try to change the source ports we are bound to.
+ */
+static void
+change_source_ports ()
+{
+  struct GNUNET_NETWORK_Handle *old4;
+  struct GNUNET_NETWORK_Handle *old6;
+
+  if (GNUNET_SCHEDULER_NO_TASK != read4_task)
+  {
+    GNUNET_SCHEDULER_cancel (read4_task);
+    read4_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != read6_task)
+  {
+    GNUNET_SCHEDULER_cancel (read6_task);
+    read6_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  old4 = dnsout4;
+  if (GNUNET_OK != open_port4 ())
+  {
+    dnsout4 = old4;
+    read4_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                               dnsout4,
+                                               &read_response, dnsout4);
+  }
+  else
+  {
+    if (NULL != old4)
+      GNUNET_NETWORK_socket_close (old4);
+  }
+  old6 = dnsout6;
+  if (GNUNET_OK != open_port6 ())
+  {
+    dnsout6 = old6;
+    read6_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                               dnsout6,
+                                               &read_response, dnsout6);
+  }
+  else
+  {
+    if (NULL != old6)
+      GNUNET_NETWORK_socket_close (old6);
+  }
+}
+
+
+/**
  * We got a new client.  Make sure all new DNS requests pass by its desk.
  *
  * @param cls unused
@@ -1216,6 +1234,12 @@
 
   /* clean up from previous request */
   GNUNET_free_non_null (rr->payload);
+  if (RP_INTERNET_DNS == rr->phase)
+  {
+    dns_active--;
+    if (0 == dns_active)
+      change_source_ports ();
+  }
   rr->payload = NULL;
   GNUNET_array_grow (rr->client_wait_list,
                     rr->client_wait_list_length,
@@ -1435,7 +1459,6 @@
     {&handle_client_response, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, 
0},
     {NULL, NULL, 0, 0}
   };
-  char port_s[6];
   char *ifc_name;
   char *ipv4addr;
   char *ipv4mask;
@@ -1514,12 +1537,7 @@
     return;
   }
   helper_argv[5] = ipv4mask;
-  GNUNET_snprintf (port_s, 
-                  sizeof (port_s), 
-                  "%u", 
-                  (unsigned int) dnsoutport);
-  helper_argv[6] = GNUNET_strdup (port_s);
-  helper_argv[7] = NULL;
+  helper_argv[6] = NULL;
 
   if (NULL != dns_exit)
   {




reply via email to

[Prev in Thread] Current Thread [Next in Thread]