Fix perf_crypto_rsa.c after various changes
[oweals/gnunet.git] / src / util / socks.c
index 43201c53b66dea51694b0cc16413ea53544f364e..bda8765ad9a4c18863db2be5bda7a21d459976ed 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2009-2013 Jeffrey Burdges (and other contributing authors)
+     Copyright (C) 2009-2013 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -34,7 +34,6 @@
 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "socks", syscall)
 
 
-
 /* SOCKS5 authentication methods */
 #define SOCKS5_AUTH_REJECT 0xFF /* No acceptable auth method */
 #define SOCKS5_AUTH_NOAUTH 0x00 /* without authentication */
@@ -106,7 +105,7 @@ unsigned char * SOCK5_proto_string(unsigned char * b, const char * s)
 /**
  * State of the SOCKS5 handshake.
  */
-struct GNUNET_SOCKS_Handshake 
+struct GNUNET_SOCKS_Handshake
 {
 
   /**
@@ -125,7 +124,7 @@ struct GNUNET_SOCKS_Handshake
   struct GNUNET_CONNECTION_TransmitHandle *th;
 
   /**
-   * Our stage in the SOCKS5 handshake 
+   * Our stage in the SOCKS5 handshake
    */
   int step;
 
@@ -164,8 +163,7 @@ register_reciever (struct GNUNET_SOCKS_Handshake *ih, int want);
 
 
 struct GNUNET_CONNECTION_TransmitHandle *
-register_sender (struct GNUNET_SOCKS_Handshake *ih, 
-                 struct GNUNET_TIME_Relative timeout);
+register_sender (struct GNUNET_SOCKS_Handshake *ih);
 
 
 /**
@@ -201,7 +199,7 @@ SOCKS5_handshake_step (struct GNUNET_SOCKS_Handshake *ih)
   GNUNET_assert (SOCKS5_step_done > ih->step && ih->step >= 0);
   switch (ih->step) {
     case SOCKS5_step_greet:  /* SOCKS5 server's greeting */
-      if (b[0] != 5) 
+      if (b[0] != 5)
       {
         LOG (GNUNET_ERROR_TYPE_ERROR,
              "Not a SOCKS5 server\n");
@@ -236,7 +234,7 @@ SOCKS5_handshake_step (struct GNUNET_SOCKS_Handshake *ih)
       b += 2;
       break;
     case SOCKS5_step_cmd:  /* SOCKS5 server's responce to command */
-      if (b[0] != 5) 
+      if (b[0] != 5)
       {
         LOG (GNUNET_ERROR_TYPE_ERROR,
              "SOCKS5 protocol error\n");
@@ -273,13 +271,13 @@ SOCKS5_handshake_step (struct GNUNET_SOCKS_Handshake *ih)
       ih->instart = b;
       SOCKS5_handshake_done (ih);
       return;
-    case SOCKS5_step_done: 
+    case SOCKS5_step_done:
       GNUNET_assert (0);
   }
   ih->instart = b;
-  /* Do not reschedule the sender unless we're done reading. 
+  /* Do not reschedule the sender unless we're done reading.
    * I imagine this lets us avoid ever cancelling the transmit handle. */
-  register_sender (ih, GNUNET_TIME_relative_get_minute_ ());
+  register_sender (ih);
 }
 
 
@@ -291,7 +289,7 @@ SOCKS5_handshake_step (struct GNUNET_SOCKS_Handshake *ih)
  * @param handler_cls closure for @a handler
  */
 void
-reciever (void *cls, 
+reciever (void *cls,
           const void *buf, size_t available,
           const struct sockaddr * addr,
           socklen_t addrlen, int errCode)
@@ -330,9 +328,8 @@ register_reciever (struct GNUNET_SOCKS_Handshake *ih, int want)
  * @param buf where the callee should write the message
  * @return number of bytes written to @a buf
  */
-
 size_t
-transmit_ready (void *cls, 
+transmit_ready (void *cls,
                 size_t size,
                 void *buf)
 {
@@ -347,26 +344,38 @@ transmit_ready (void *cls,
    * GNUNET_CONNECTION_notify_transmit_ready() can schedule :
    *   transmit_timeout() - DNS still working
    *   connect_error() - DNS done but no socket?
-   * transmit_ready() - scheduler shutdown or timeout, or signal_transmit_error() 
+   * transmit_ready() - scheduler shutdown or timeout, or signal_transmit_error()
    * We'd need to dig into the scheduler to guess at the reason, as
    * connection.c tells us nothing itself, but mostly its timouts.
    * Initially, we'll simply ignore this and leave massive timeouts, but
    * maybe that should change for error handling pruposes.  It appears that
    * successful operations, including DNS resolution, do not use this.  */
-  if (NULL==buf)
+  if (NULL == buf)
   {
-    GNUNET_break (0);
+    if (0 == ih->step)
+    {
+      LOG (GNUNET_ERROR_TYPE_WARNING,
+          "Timeout contacting SOCKS server, retrying indefinitely, but probably hopeless.\n");
+      register_sender (ih);
+    }
+    else
+    {
+      LOG (GNUNET_ERROR_TYPE_ERROR,
+          "Timeout during mid SOCKS handshake (step %u), probably not a SOCKS server.\n",
+          ih->step);
+      GNUNET_break (0);
+    }
     return 0;
   }
 
   GNUNET_assert (1024 >= size && size > 0);
   GNUNET_assert (SOCKS5_step_done > ih->step && ih->step >= 0);
   unsigned char * b = ih->outstep[ih->step];
-  unsigned char * e = ih->outstep[ih->step++];
+  unsigned char * e = ih->outstep[ih->step+1];
   GNUNET_assert (e <= &ih->outbuf[1024]);
   unsigned l = e - b;
   GNUNET_assert (size >= l && l >= 0);
-  memcpy(b, buf, l);
+  memcpy(buf, b, l);
   register_reciever (ih, register_reciever_wants(ih));
   return l;
 }
@@ -380,10 +389,14 @@ transmit_ready (void *cls,
  *         NULL if we are already going to notify someone else (busy)
  */
 struct GNUNET_CONNECTION_TransmitHandle *
-register_sender (struct GNUNET_SOCKS_Handshake *ih, 
-                 struct GNUNET_TIME_Relative timeout)
+register_sender (struct GNUNET_SOCKS_Handshake *ih)
 {
-  GNUNET_assert (SOCKS5_step_done > ih->step && ih->step >= 0);
+  struct GNUNET_TIME_Relative timeout = GNUNET_TIME_UNIT_MINUTES;
+
+  GNUNET_assert (SOCKS5_step_done > ih->step);
+  GNUNET_assert (ih->step >= 0);
+  if (0 == ih->step)
+    timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3);
   unsigned char * b = ih->outstep[ih->step];
   unsigned char * e = ih->outstep[ih->step+1];
   GNUNET_assert (ih->outbuf <= b && b < e && e < &ih->outbuf[1024]);
@@ -399,7 +412,7 @@ register_sender (struct GNUNET_SOCKS_Handshake *ih,
 /**
  * Initialize a SOCKS5 handshake for authentication via username and
  * password.  Tor uses SOCKS username and password authentication to assign
- * programs unique circuits. 
+ * programs unique circuits.
  *
  * @param user username for the proxy
  * @param pass password for the proxy
@@ -416,7 +429,7 @@ GNUNET_SOCKS_init_handshake (const char *user, const char *pass)
   unsigned char * n = b++;
   *n = 1; /* Number of authentication methods */
   /* We support no authentication even when requesting authentication,
-   * but this appears harmless, given the way that Tor uses authentication. 
+   * but this appears harmless, given the way that Tor uses authentication.
    * And some SOCKS5 servers might require this.  */
   *(b++) = SOCKS5_AUTH_NOAUTH;
   if (NULL != user) {
@@ -426,11 +439,11 @@ GNUNET_SOCKS_init_handshake (const char *user, const char *pass)
   /* There is no apperent reason to support authentication methods beyond
    * username and password since afaik Tor does not support them. */
 
-  /* We authenticate with an empty username and password if the server demands 
+  /* We authenticate with an empty username and password if the server demands
    * them but we do not have any. */
   if (user == NULL)
     user = "";
-  if (user == NULL)
+  if (pass == NULL)
     pass = "";
 
   ih->outstep[SOCKS5_step_auth] = b;
@@ -440,12 +453,14 @@ GNUNET_SOCKS_init_handshake (const char *user, const char *pass)
 
   ih->outstep[SOCKS5_step_cmd] = b;
 
+  ih->inend = ih->instart = ih->inbuf;
+
   return ih;
 }
 
 
 /**
- * Initialize a SOCKS5 handshake without authentication, thereby possibly 
+ * Initialize a SOCKS5 handshake without authentication, thereby possibly
  * sharing a Tor circuit with another process.
  *
  * @return Valid SOCKS5 hanbdshake handle
@@ -459,11 +474,11 @@ GNUNET_SOCKS_init_handshake_noauth ()
 
 /**
  * Build request that the SOCKS5 proxy open a TCP/IP stream to the given host
- * and port.  
+ * and port.
  *
  * @param ih SOCKS5 handshake
- * @param hostname 
- * @param port 
+ * @param hostname
+ * @param port
  */
 void
 GNUNET_SOCKS_set_handshake_destination (struct GNUNET_SOCKS_Handshake *ih,
@@ -508,13 +523,14 @@ GNUNET_SOCKS_set_handshake_destination (struct GNUNET_SOCKS_Handshake *ih,
  * @param c open unused connection, consumed here.
  * @return Connection handle that becomes usable when the SOCKS5 handshake completes.
  */
-struct GNUNET_CONNECTION_Handle * 
+struct GNUNET_CONNECTION_Handle *
 GNUNET_SOCKS_run_handshake(struct GNUNET_SOCKS_Handshake *ih,
                             struct GNUNET_CONNECTION_Handle *c)
 {
   ih->socks5_connection=c;
   ih->target_connection = GNUNET_CONNECTION_create_proxied_from_handshake (c);
-  register_sender (ih, GNUNET_TIME_relative_get_forever_ () );
+  register_sender (ih);
+
   return ih->target_connection;
 }
 
@@ -558,7 +574,7 @@ GNUNET_SOCKS_do_connect (const char *service_name,
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "SOCKSPORT", &port0))
     port0 = 9050;
-  /* A typical Tor client should usually try port 9150 for the TBB too, but 
+  /* A typical Tor client should usually try port 9150 for the TBB too, but
    * GUNNet can probably assume a system Tor instalation. */
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "SOCKSHOST", &host0))
@@ -567,8 +583,8 @@ GNUNET_SOCKS_do_connect (const char *service_name,
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
         _
-        ("Attempting to use invalid port or hostname for SOCKS proxy for service `%s'.\n"),
-        service_name);
+        ("Attempting to use invalid port %d as SOCKS proxy for service `%s'.\n"),
+        port0,service_name);
     return NULL;
   }
 
@@ -576,12 +592,12 @@ GNUNET_SOCKS_do_connect (const char *service_name,
        GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "PORT", &port1))
       || (port1 > 65535) || (port1 <= 0) ||
        (GNUNET_OK !=
-        GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "HOST", &host1)))
+        GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "HOSTNAME", &host1)))
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
         _
-        ("Attempting to proxy service `%s' to invalid port or hostname.\n"),
-        service_name);
+        ("Attempting to proxy service `%s' to invalid port %d or hostname `%s'.\n"),
+        service_name,port1,host1);
     return NULL;
   }
 
@@ -592,6 +608,9 @@ GNUNET_SOCKS_do_connect (const char *service_name,
   GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "SOCKSUSER", &user);
   GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "SOCKSPASS", &pass);
   ih = GNUNET_SOCKS_init_handshake(user,pass);
+  if (NULL != user) GNUNET_free (user);
+  if (NULL != pass) GNUNET_free (pass);
+
   GNUNET_SOCKS_set_handshake_destination (ih,host1,port1);
   GNUNET_free (host1);