-ensure stats queues do not grow too big
[oweals/gnunet.git] / src / gns / gnunet-gns-proxy.c
index 968470bd97fcb589e2d1cf8041e1ccfbd3c122a5..7ab8843bba2a756e07758bc94fd51e8f42bc149b 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2012-2013 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2012-2014 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
@@ -14,8 +14,8 @@
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 /**
  * @author Martin Schanzenbach
  *
  * TODO:
  * - double-check queueing logic
- * - actually check SSL certificates (#3038)
  */
 #include "platform.h"
 #include <microhttpd.h>
+#if HAVE_CURL_CURL_H
 #include <curl/curl.h>
+#elif HAVE_GNURL_CURL_H
+#include <gnurl/curl.h>
+#endif
 #include <gnutls/gnutls.h>
 #include <gnutls/x509.h>
 #include <gnutls/abstract.h>
@@ -357,7 +360,7 @@ struct MhdHttpList
   /**
    * The task ID
    */
-  GNUNET_SCHEDULER_TaskIdentifier httpd_task;
+  struct GNUNET_SCHEDULER_Task *httpd_task;
 
   /**
    * is this an ssl daemon?
@@ -457,17 +460,17 @@ struct Socks5Request
   /**
    * Client socket read task
    */
-  GNUNET_SCHEDULER_TaskIdentifier rtask;
+  struct GNUNET_SCHEDULER_Task * rtask;
 
   /**
    * Client socket write task
    */
-  GNUNET_SCHEDULER_TaskIdentifier wtask;
+  struct GNUNET_SCHEDULER_Task * wtask;
 
   /**
    * Timeout task
    */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+  struct GNUNET_SCHEDULER_Task * timeout_task;
 
   /**
    * Read buffer
@@ -524,6 +527,11 @@ struct Socks5Request
    */
   struct curl_slist *headers;
 
+  /**
+   * DNS->IP mappings resolved through GNS
+   */
+  struct curl_slist *hosts;
+
   /**
    * HTTP response code to give to MHD for the response.
    */
@@ -594,17 +602,17 @@ static struct GNUNET_NETWORK_Handle *lsock6;
 /**
  * The listen task ID for IPv4
  */
-static GNUNET_SCHEDULER_TaskIdentifier ltask4;
+static struct GNUNET_SCHEDULER_Task * ltask4;
 
 /**
  * The listen task ID for IPv6
  */
-static GNUNET_SCHEDULER_TaskIdentifier ltask6;
+static struct GNUNET_SCHEDULER_Task * ltask6;
 
 /**
  * The cURL download task (curl multi API).
  */
-static GNUNET_SCHEDULER_TaskIdentifier curl_download_task;
+static struct GNUNET_SCHEDULER_Task * curl_download_task;
 
 /**
  * The cURL multi handle
@@ -714,14 +722,18 @@ cleanup_s5r (struct Socks5Request *s5r)
     s5r->curl = NULL;
   }
   curl_slist_free_all (s5r->headers);
+  if (NULL != s5r->hosts)
+  {
+    curl_slist_free_all (s5r->hosts);
+  }
   if ( (NULL != s5r->response) &&
        (curl_failure_response != s5r->response) )
     MHD_destroy_response (s5r->response);
-  if (GNUNET_SCHEDULER_NO_TASK != s5r->rtask)
+  if (NULL != s5r->rtask)
     GNUNET_SCHEDULER_cancel (s5r->rtask);
-  if (GNUNET_SCHEDULER_NO_TASK != s5r->timeout_task)
+  if (NULL != s5r->timeout_task)
     GNUNET_SCHEDULER_cancel (s5r->timeout_task);
-  if (GNUNET_SCHEDULER_NO_TASK != s5r->wtask)
+  if (NULL != s5r->wtask)
     GNUNET_SCHEDULER_cancel (s5r->wtask);
   if (NULL != s5r->gns_lookup)
     GNUNET_GNS_lookup_cancel (s5r->gns_lookup);
@@ -814,34 +826,28 @@ mhd_content_cb (void *cls,
 static int
 check_ssl_certificate (struct Socks5Request *s5r)
 {
-  struct curl_tlsinfo tlsinfo;
   unsigned int cert_list_size;
   const gnutls_datum_t *chainp;
-  union {
-    struct curl_tlsinfo *tlsinfo;
-    struct curl_slist   *to_slist;
-  } gptr;
+  const struct curl_tlssessioninfo *tlsinfo;
   char certdn[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 3];
   size_t size;
   gnutls_x509_crt_t x509_cert;
   int rc;
   const char *name;
 
-  memset (&tlsinfo, 0, sizeof (tlsinfo));
-  gptr.tlsinfo = &tlsinfo;
   if (CURLE_OK !=
       curl_easy_getinfo (s5r->curl,
                         CURLINFO_TLS_SESSION,
-                        &gptr))
+                        (struct curl_slist **) &tlsinfo))
     return GNUNET_SYSERR;
-  if (CURLSSLBACKEND_GNUTLS != tlsinfo.ssl_backend)
+  if (CURLSSLBACKEND_GNUTLS != tlsinfo->backend)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 _("Unsupported CURL SSL backend %d\n"),
-                tlsinfo.ssl_backend);
+                tlsinfo->backend);
     return GNUNET_SYSERR;
   }
-  chainp = gnutls_certificate_get_peers (tlsinfo.internals, &cert_list_size);
+  chainp = gnutls_certificate_get_peers (tlsinfo->internals, &cert_list_size);
   if ( (! chainp) || (0 == cert_list_size) )
     return GNUNET_SYSERR;
 
@@ -877,6 +883,9 @@ check_ssl_certificate (struct Socks5Request *s5r)
 
     /* FIXME: add flags to gnutls to NOT read UNBOUND_ROOT_KEY_FILE here! */
     if (0 != (rc = dane_state_init (&dane_state,
+#ifdef DANE_F_IGNORE_DNSSEC
+                                    DANE_F_IGNORE_DNSSEC |
+#endif
                                     DANE_F_IGNORE_LOCAL_RESOLVER)))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -902,7 +911,7 @@ check_ssl_certificate (struct Socks5Request *s5r)
     if (0 != (rc = dane_verify_crt_raw (dane_state,
                                         chainp,
                                         cert_list_size,
-                                        gnutls_certificate_type_get (tlsinfo.internals),
+                                        gnutls_certificate_type_get (tlsinfo->internals),
                                         dane_query,
                                         0, 0,
                                         &verify)))
@@ -957,36 +966,6 @@ check_ssl_certificate (struct Socks5Request *s5r)
     }
   }
   gnutls_x509_crt_deinit (x509_cert);
-#if 0
-  {
-  unsigned int i;
-
-  for(i=0;i<cert_list_size;i++)
-  {
-    gnutls_x509_crt_t cert;
-    gnutls_datum_t dn;
-
-    if (GNUTLS_E_SUCCESS == gnutls_x509_crt_init (&cert))
-    {
-      if (GNUTLS_E_SUCCESS ==
-          gnutls_x509_crt_import (cert, &chainp[i],
-                                  GNUTLS_X509_FMT_DER))
-      {
-        if (GNUTLS_E_SUCCESS ==
-            gnutls_x509_crt_print (cert,
-                                   GNUTLS_CRT_PRINT_FULL,
-                                   &dn))
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      "Certificate #%d: %.*s", i, dn.size, dn.data);
-          gnutls_free (dn.data);
-        }
-      }
-      gnutls_x509_crt_deinit (cert);
-    }
-  }
-  }
-#endif
   return GNUNET_OK;
 }
 
@@ -1057,7 +1036,7 @@ curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls)
       GNUNET_free (cors_hdr);
     }
     /* force connection to be closed after each request, as we
-       do not support HTTP pipelining */
+       do not support HTTP pipelining (yet, FIXME!) */
     GNUNET_break (MHD_YES ==
                  MHD_add_response_header (s5r->response,
                                           MHD_HTTP_HEADER_CONNECTION,
@@ -1278,10 +1257,9 @@ curl_upload_cb (void *buf, size_t size, size_t nmemb, void *cls)
  * from curl
  *
  * @param cls closure
- * @param tc task context
  */
 static void
-curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+curl_task_download (void *cls);
 
 
 /**
@@ -1300,10 +1278,10 @@ curl_download_prepare ()
   long to;
   struct GNUNET_TIME_Relative rtime;
 
-  if (GNUNET_SCHEDULER_NO_TASK != curl_download_task)
+  if (NULL != curl_download_task)
   {
     GNUNET_SCHEDULER_cancel (curl_download_task);
-    curl_download_task = GNUNET_SCHEDULER_NO_TASK;
+    curl_download_task = NULL;
   }
   max = -1;
   FD_ZERO (&rs);
@@ -1349,11 +1327,9 @@ curl_download_prepare ()
  * Task that is run when we are ready to receive more data from curl.
  *
  * @param cls closure, NULL
- * @param tc task context
  */
 static void
-curl_task_download (void *cls,
-                   const struct GNUNET_SCHEDULER_TaskContext *tc)
+curl_task_download (void *cls)
 {
   int running;
   int msgnum;
@@ -1361,7 +1337,7 @@ curl_task_download (void *cls,
   CURLMcode mret;
   struct Socks5Request *s5r;
 
-  curl_download_task = GNUNET_SCHEDULER_NO_TASK;
+  curl_download_task = NULL;
   do
   {
     running = 0;
@@ -1371,7 +1347,7 @@ curl_task_download (void *cls,
       GNUNET_break (CURLE_OK ==
                    curl_easy_getinfo (msg->easy_handle,
                                       CURLINFO_PRIVATE,
-                                      &s5r));
+                                      (char **) &s5r ));
       if (NULL == s5r)
       {
        GNUNET_break (0);
@@ -1513,9 +1489,9 @@ create_response (void *cls,
                  size_t *upload_data_size,
                  void **con_cls)
 {
-  /* struct MhdHttpList* hd = cls;  */
   struct Socks5Request *s5r = *con_cls;
   char *curlurl;
+  char *curl_hosts;
   char ipstring[INET6_ADDRSTRLEN];
   char ipaddr[INET6_ADDRSTRLEN + 2];
   const struct sockaddr *sa;
@@ -1589,11 +1565,29 @@ create_response (void *cls,
     curl_easy_setopt (s5r->curl, CURLOPT_NOSIGNAL, 1L);
     curl_easy_setopt (s5r->curl, CURLOPT_PRIVATE, s5r);
     curl_easy_setopt (s5r->curl, CURLOPT_VERBOSE, 0);
+    /**
+     * Pre-populate cache to resolve Hostname.
+     * This is necessary as the DNS name in the CURLOPT_URL is used
+     * for SNI http://de.wikipedia.org/wiki/Server_Name_Indication
+     */
+    if (NULL != s5r->leho)
+    {
+        GNUNET_asprintf (&curl_hosts,
+                         "%s:%d:%s",
+                         s5r->leho,
+                         port,
+                         ipaddr);
+        s5r->hosts = curl_slist_append(NULL, curl_hosts);
+        curl_easy_setopt(s5r->curl, CURLOPT_RESOLVE, s5r->hosts);
+        GNUNET_free (curl_hosts);
+    }
     GNUNET_asprintf (&curlurl,
                     (HTTPS_PORT != s5r->port)
                     ? "http://%s:%d%s"
                     : "https://%s:%d%s",
-                    ipaddr,
+                    (NULL != s5r->leho)
+                     ? s5r->leho
+                     : ipaddr,
                     port,
                     s5r->url);
     curl_easy_setopt (s5r->curl,
@@ -1722,7 +1716,7 @@ create_response (void *cls,
  * @param cls NULL
  * @param connection connection handle
  * @param con_cls value as set by the last call to
- *        the MHD_AccessHandlerCallback, should be our `struct Socks5Request`
+ *        the MHD_AccessHandlerCallback, should be our `struct Socks5Request *`
  * @param toe reason for request termination (ignored)
  */
 static void
@@ -1740,6 +1734,7 @@ mhd_completed_cb (void *cls,
                "MHD encountered error handling request: %d\n",
                toe);
   cleanup_s5r (s5r);
+  curl_download_prepare();
   *con_cls = NULL;
 }
 
@@ -1785,10 +1780,11 @@ mhd_log_callback (void *cls,
       }
       s5r->url = GNUNET_strdup (url);
       GNUNET_SCHEDULER_cancel (s5r->timeout_task);
-      s5r->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+      s5r->timeout_task = NULL;
       return s5r;
     }
   }
+  GNUNET_break (0);
   return NULL;
 }
 
@@ -1806,10 +1802,10 @@ kill_httpd (struct MhdHttpList *hd)
                               hd);
   GNUNET_free_non_null (hd->domain);
   MHD_stop_daemon (hd->daemon);
-  if (GNUNET_SCHEDULER_NO_TASK != hd->httpd_task)
+  if (NULL != hd->httpd_task)
   {
     GNUNET_SCHEDULER_cancel (hd->httpd_task);
-    hd->httpd_task = GNUNET_SCHEDULER_NO_TASK;
+    hd->httpd_task = NULL;
   }
   GNUNET_free_non_null (hd->proxy_cert);
   if (hd == httpd)
@@ -1822,15 +1818,13 @@ kill_httpd (struct MhdHttpList *hd)
  * Task run whenever HTTP server is idle for too long. Kill it.
  *
  * @param cls the `struct MhdHttpList *`
- * @param tc sched context
  */
 static void
-kill_httpd_task (void *cls,
-                const struct GNUNET_SCHEDULER_TaskContext *tc)
+kill_httpd_task (void *cls)
 {
   struct MhdHttpList *hd = cls;
 
-  hd->httpd_task = GNUNET_SCHEDULER_NO_TASK;
+  hd->httpd_task = NULL;
   kill_httpd (hd);
 }
 
@@ -1839,11 +1833,9 @@ kill_httpd_task (void *cls,
  * Task run whenever HTTP server operations are pending.
  *
  * @param cls the `struct MhdHttpList *` of the daemon that is being run
- * @param tc sched context
  */
 static void
-do_httpd (void *cls,
-          const struct GNUNET_SCHEDULER_TaskContext *tc);
+do_httpd (void *cls);
 
 
 /**
@@ -1892,7 +1884,7 @@ schedule_httpd (struct MhdHttpList *hd)
     wrs = NULL;
     wws = NULL;
   }
-  if (GNUNET_SCHEDULER_NO_TASK != hd->httpd_task)
+  if (NULL != hd->httpd_task)
     GNUNET_SCHEDULER_cancel (hd->httpd_task);
   if ( (MHD_YES != haveto) &&
        (-1 == max) &&
@@ -1921,15 +1913,13 @@ schedule_httpd (struct MhdHttpList *hd)
  * Task run whenever HTTP server operations are pending.
  *
  * @param cls the `struct MhdHttpList` of the daemon that is being run
- * @param tc scheduler context
  */
 static void
-do_httpd (void *cls,
-          const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_httpd (void *cls)
 {
   struct MhdHttpList *hd = cls;
 
-  hd->httpd_task = GNUNET_SCHEDULER_NO_TASK;
+  hd->httpd_task = NULL;
   MHD_run (hd->daemon);
   schedule_httpd (hd);
 }
@@ -1943,7 +1933,7 @@ do_httpd (void *cls,
 static void
 run_mhd_now (struct MhdHttpList *hd)
 {
-  if (GNUNET_SCHEDULER_NO_TASK !=
+  if (NULL !=
       hd->httpd_task)
     GNUNET_SCHEDULER_cancel (hd->httpd_task);
   hd->httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd,
@@ -2065,7 +2055,7 @@ generate_gns_certificate (const char *name)
   GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_set_key (request, proxy_ca.key));
   pgc = GNUNET_new (struct ProxyGNSCertificate);
   gnutls_x509_crt_set_dn_by_oid (request, GNUTLS_OID_X520_COUNTRY_NAME,
-                                 0, "TNR", 2);
+                                 0, "ZZ", 2);
   gnutls_x509_crt_set_dn_by_oid (request, GNUTLS_OID_X520_ORGANIZATION_NAME,
                                  0, "GNU Name System", 4);
   gnutls_x509_crt_set_dn_by_oid (request, GNUTLS_OID_X520_COMMON_NAME,
@@ -2117,7 +2107,7 @@ mhd_error_log_callback (void *cls,
  * Lookup (or create) an SSL MHD instance for a particular domain.
  *
  * @param domain the domain the SSL daemon has to serve
- * @return NULL on errro
+ * @return NULL on error
  */
 static struct MhdHttpList *
 lookup_ssl_httpd (const char* domain)
@@ -2125,6 +2115,11 @@ lookup_ssl_httpd (const char* domain)
   struct MhdHttpList *hd;
   struct ProxyGNSCertificate *pgc;
 
+  if (NULL == domain)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
   for (hd = mhd_httpd_head; NULL != hd; hd = hd->next)
     if ( (NULL != hd->domain) &&
         (0 == strcmp (hd->domain, domain)) )
@@ -2167,15 +2162,13 @@ lookup_ssl_httpd (const char* domain)
  * the SOCKS5 handshake).  Clean up.
  *
  * @param cls the `struct Socks5Request *`
- * @param tc sched context
  */
 static void
-timeout_s5r_handshake (void *cls,
-                      const struct GNUNET_SCHEDULER_TaskContext *tc)
+timeout_s5r_handshake (void *cls)
 {
   struct Socks5Request *s5r = cls;
 
-  s5r->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  s5r->timeout_task = NULL;
   cleanup_s5r (s5r);
 }
 
@@ -2241,16 +2234,14 @@ setup_data_transfer (struct Socks5Request *s5r)
  * Write data from buffer to socks5 client, then continue with state machine.
  *
  * @param cls the closure with the `struct Socks5Request`
- * @param tc scheduler context
  */
 static void
-do_write (void *cls,
-         const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_write (void *cls)
 {
   struct Socks5Request *s5r = cls;
   ssize_t len;
 
-  s5r->wtask = GNUNET_SCHEDULER_NO_TASK;
+  s5r->wtask = NULL;
   len = GNUNET_NETWORK_socket_send (s5r->sock,
                                    s5r->wbuf,
                                    s5r->wbuf_len);
@@ -2282,7 +2273,7 @@ do_write (void *cls,
     GNUNET_assert (0);
     break;
   case SOCKS5_REQUEST:
-    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s5r->rtask);
+    GNUNET_assert (NULL != s5r->rtask);
     break;
   case SOCKS5_DATA_TRANSFER:
     setup_data_transfer (s5r);
@@ -2314,7 +2305,7 @@ signal_socks_failure (struct Socks5Request *s5r,
   s_resp->version = SOCKS_VERSION_5;
   s_resp->reply = sc;
   s5r->state = SOCKS5_WRITE_THEN_CLEANUP;
-  if (GNUNET_SCHEDULER_NO_TASK != s5r->wtask)
+  if (NULL != s5r->wtask)
     s5r->wtask =
       GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                      s5r->sock,
@@ -2343,7 +2334,7 @@ signal_socks_success (struct Socks5Request *s5r)
          sizeof (struct in_addr) + sizeof (uint16_t));
   s5r->wbuf_len += sizeof (struct Socks5ServerResponseMessage) +
     sizeof (struct in_addr) + sizeof (uint16_t);
-  if (GNUNET_SCHEDULER_NO_TASK == s5r->wtask)
+  if (NULL == s5r->wtask)
     s5r->wtask =
       GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                      s5r->sock,
@@ -2354,7 +2345,7 @@ signal_socks_success (struct Socks5Request *s5r)
 /**
  * Process GNS results for target domain.
  *
- * @param cls the `struct Socks5Request`
+ * @param cls the `struct Socks5Request *`
  * @param rd_count number of records returned
  * @param rd record data
  */
@@ -2436,14 +2427,28 @@ handle_gns_result (void *cls,
       s5r->leho = GNUNET_strndup (r->data,
                                  r->data_size);
       break;
-    case GNUNET_DNSPARSER_TYPE_TLSA:
-      GNUNET_free_non_null (s5r->dane_data);
-      s5r->dane_data_len = r->data_size;
-      s5r->dane_data = GNUNET_malloc (r->data_size);
-      memcpy (s5r->dane_data,
-              r->data,
-              r->data_size);
-      break;
+    case GNUNET_GNSRECORD_TYPE_BOX:
+      {
+        const struct GNUNET_GNSRECORD_BoxRecord *box;
+
+        if (r->data_size < sizeof (struct GNUNET_GNSRECORD_BoxRecord))
+        {
+          GNUNET_break_op (0);
+          break;
+        }
+        box = r->data;
+        if ( (ntohl (box->record_type) != GNUNET_DNSPARSER_TYPE_TLSA) ||
+             (ntohs (box->protocol) != IPPROTO_TCP) ||
+             (ntohs (box->service) != s5r->port) )
+          break; /* BOX record does not apply */
+        GNUNET_free_non_null (s5r->dane_data);
+        s5r->dane_data_len = r->data_size - sizeof (struct GNUNET_GNSRECORD_BoxRecord);
+        s5r->dane_data = GNUNET_malloc (s5r->dane_data_len);
+        memcpy (s5r->dane_data,
+                &box[1],
+                s5r->dane_data_len);
+        break;
+      }
     default:
       /* don't care */
       break;
@@ -2484,11 +2489,9 @@ clear_from_s5r_rbuf (struct Socks5Request *s5r,
  * Read data from incoming Socks5 connection
  *
  * @param cls the closure with the `struct Socks5Request`
- * @param tc the scheduler context
  */
 static void
-do_s5r_read (void *cls,
-            const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_s5r_read (void *cls)
 {
   struct Socks5Request *s5r = cls;
   const struct Socks5ClientHelloMessage *c_hello;
@@ -2496,8 +2499,10 @@ do_s5r_read (void *cls,
   const struct Socks5ClientRequestMessage *c_req;
   ssize_t rlen;
   size_t alen;
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
 
-  s5r->rtask = GNUNET_SCHEDULER_NO_TASK;
+  s5r->rtask = NULL;
+  tc = GNUNET_SCHEDULER_get_task_context ();
   if ( (NULL != tc->read_ready) &&
        (GNUNET_NETWORK_fdset_isset (tc->read_ready, s5r->sock)) )
   {
@@ -2517,7 +2522,7 @@ do_s5r_read (void *cls,
                                              s5r->sock,
                                              &do_s5r_read, s5r);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Processing %u bytes of socks data in state %d\n",
+             "Processing %zu bytes of socks data in state %d\n",
              s5r->rbuf_len,
              s5r->state);
   switch (s5r->state)
@@ -2542,7 +2547,7 @@ do_s5r_read (void *cls,
     s5r->wbuf_len = sizeof (struct Socks5ServerHelloMessage);
     s_hello->version = SOCKS_VERSION_5;
     s_hello->auth_method = SOCKS_AUTH_NONE;
-    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s5r->wtask);
+    GNUNET_assert (NULL == s5r->wtask);
     s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                                 s5r->sock,
                                                 &do_write, s5r);
@@ -2574,6 +2579,14 @@ do_s5r_read (void *cls,
        struct sockaddr_in *in;
 
        s5r->port = ntohs (*port);
+        if (HTTPS_PORT == s5r->port)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      _("SSL connection to plain IPv4 address requested\n"));
+          signal_socks_failure (s5r,
+                                SOCKS5_STATUS_CONNECTION_NOT_ALLOWED_BY_RULE);
+          return;
+        }
        alen = sizeof (struct in_addr);
        if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) +
            alen + sizeof (uint16_t))
@@ -2595,6 +2608,14 @@ do_s5r_read (void *cls,
        struct sockaddr_in6 *in;
 
        s5r->port = ntohs (*port);
+        if (HTTPS_PORT == s5r->port)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      _("SSL connection to plain IPv4 address requested\n"));
+          signal_socks_failure (s5r,
+                                SOCKS5_STATUS_CONNECTION_NOT_ALLOWED_BY_RULE);
+          return;
+        }
        alen = sizeof (struct in6_addr);
        if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) +
            alen + sizeof (uint16_t))
@@ -2665,7 +2686,7 @@ do_s5r_read (void *cls,
     }
     /* We are done reading right now */
     GNUNET_SCHEDULER_cancel (s5r->rtask);
-    s5r->rtask = GNUNET_SCHEDULER_NO_TASK;
+    s5r->rtask = NULL;
     return;
   case SOCKS5_RESOLVING:
     GNUNET_assert (0);
@@ -2687,19 +2708,16 @@ do_s5r_read (void *cls,
  * @param tc the scheduler context
  */
 static void
-do_accept (void *cls,
-          const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_accept (void *cls)
 {
   struct GNUNET_NETWORK_Handle *lsock = cls;
   struct GNUNET_NETWORK_Handle *s;
   struct Socks5Request *s5r;
 
   if (lsock == lsock4)
-    ltask4 = GNUNET_SCHEDULER_NO_TASK;
+    ltask4 = NULL;
   else
-    ltask6 = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
+    ltask6 = NULL;
   if (lsock == lsock4)
     ltask4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                             lsock,
@@ -2735,11 +2753,9 @@ do_accept (void *cls,
  * Task run on shutdown
  *
  * @param cls closure
- * @param tc task context
  */
 static void
-do_shutdown (void *cls,
-             const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_shutdown (void *cls)
 {
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Shutting down...\n");
@@ -2777,20 +2793,20 @@ do_shutdown (void *cls,
     GNUNET_GNS_disconnect (gns_handle);
     gns_handle = NULL;
   }
-  if (GNUNET_SCHEDULER_NO_TASK != curl_download_task)
+  if (NULL != curl_download_task)
   {
     GNUNET_SCHEDULER_cancel (curl_download_task);
-    curl_download_task = GNUNET_SCHEDULER_NO_TASK;
+    curl_download_task = NULL;
   }
-  if (GNUNET_SCHEDULER_NO_TASK != ltask4)
+  if (NULL != ltask4)
   {
     GNUNET_SCHEDULER_cancel (ltask4);
-    ltask4 = GNUNET_SCHEDULER_NO_TASK;
+    ltask4 = NULL;
   }
-  if (GNUNET_SCHEDULER_NO_TASK != ltask6)
+  if (NULL != ltask6)
   {
     GNUNET_SCHEDULER_cancel (ltask6);
-    ltask6 = GNUNET_SCHEDULER_NO_TASK;
+    ltask6 = NULL;
   }
   gnutls_x509_crt_deinit (proxy_ca.cert);
   gnutls_x509_privkey_deinit (proxy_ca.key);
@@ -2927,7 +2943,7 @@ run_cont ()
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Proxy listens on port %u\n",
+              "Proxy listens on port %lu\n",
               port);
 
   /* start MHD daemon for HTTP */
@@ -3106,8 +3122,7 @@ run (void *cls, char *const *args, const char *cfgfile,
                               "gns-proxy",
                               &identity_master_cb,
                               NULL);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
-                                &do_shutdown, NULL);
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
 }