-handle failure to load certs more nicely
[oweals/gnunet.git] / src / gns / gnunet-gns-proxy.c
index cb74c8bec300a9a275c7512dfd7f5031f0f1f27b..8bb299c6ffafc15ec1557368c21a25d094764a9a 100644 (file)
  *        with legacy browsers
  *
  * TODO:
- * - actually check SSL certificates 
  * - double-check queueing logic
- * - handle cookie rewriting
- * - handle location rewriting
- * - improve IPv6 support
+ * - improve IPv6 support (#3037)
+ * - actually check SSL certificates (#3038)
  */
 #include "platform.h"
 #include <microhttpd.h>
@@ -790,19 +788,20 @@ check_ssl_certificate (struct Socks5Request *s5r)
                         CURLINFO_CERTINFO, 
                         &ptr.to_info))
     return GNUNET_SYSERR;
-  /* FIXME: for now, we just output the certs to stderr */
+  /* FIXME: for now, we just output the certs to stderr, we should
+     check them against LEHO / TLSA record information here! (#3038) */
   if(NULL != ptr.to_info) 
   {     
-    fprintf (stderr,
-            "Got %d certs!\n", 
-            ptr.to_certinfo->num_of_certs);      
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+               "Got %d certs!\n", 
+               ptr.to_certinfo->num_of_certs);      
     for (i = 0; i < ptr.to_certinfo->num_of_certs; i++) 
     {    
       for (slist = ptr.to_certinfo->certinfo[i]; NULL != slist; slist = slist->next)
-       fprintf (stderr,
-                "%d: %s\n",
-                i,
-                slist->data);  
+       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                   "Certificate #%d: %s\n",
+                   i,
+                   slist->data);       
     }
   }
   return GNUNET_OK;
@@ -829,9 +828,15 @@ curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls)
   size_t bytes = size * nmemb;
   char *ndup;
   const char *hdr_type;
-  const char *hdr_val;
+  const char *cookie_domain;
+  char *hdr_val;
   long resp_code;
   char *new_cookie_hdr;
+  char *new_location;
+  size_t offset;
+  size_t delta_cdomain;
+  int domain_matched;
+  char *tok;
 
   if (NULL == s5r->response)
   {
@@ -891,90 +896,82 @@ curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls)
     hdr_val++;
 
   /* custom logic for certain header types */
+  new_cookie_hdr = NULL;
   if (0 == strcasecmp (hdr_type,
                       MHD_HTTP_HEADER_SET_COOKIE))
   {
-#if 0
-    // FIXME: adjust code...
+    new_cookie_hdr = GNUNET_malloc (strlen (hdr_val) + 
+                                   strlen (s5r->domain) + 1);
+    offset = 0;
+    domain_matched = GNUNET_NO; /* make sure we match domain at most once */
     for (tok = strtok (hdr_val, ";"); NULL != tok; tok = strtok (NULL, ";"))
     {
-      if (0 == memcmp (tok, " domain", strlen (" domain")))
+      if ( (0 == strncasecmp (tok, " domain", strlen (" domain"))) &&
+          (GNUNET_NO == domain_matched) )
       {
+       domain_matched = GNUNET_YES;
         cookie_domain = tok + strlen (" domain") + 1;
         if (strlen (cookie_domain) < strlen (s5r->leho))
         {
-          delta_cdomain = strlen (ctask->leho) - strlen (cookie_domain);
-          if (0 == strcmp (cookie_domain, ctask->leho + (delta_cdomain)))
-          {
-            GNUNET_snprintf (new_cookie_hdr+offset,
-                             sizeof (new_cookie_hdr),
-                             " domain=%s", ctask->authority);
-            offset += strlen (" domain=") + strlen (ctask->authority);
-            new_cookie_hdr[offset] = ';';
-            offset++;
+          delta_cdomain = strlen (s5r->leho) - strlen (cookie_domain);
+          if (0 == strcasecmp (cookie_domain, s5r->leho + delta_cdomain))
+         {
+            offset += sprintf (new_cookie_hdr + offset,
+                              " domain=%s;", 
+                              s5r->domain);
             continue;
           }
         }
-        else if (strlen (cookie_domain) == strlen (ctask->leho))
+        else if (0 == strcmp (cookie_domain, s5r->leho))
         {
-          if (0 == strcmp (cookie_domain, ctask->leho))
-          {
-            GNUNET_snprintf (new_cookie_hdr+offset,
-                             sizeof (new_cookie_hdr),
-                             " domain=%s", ctask->host);
-            offset += strlen (" domain=") + strlen (ctask->host);
-            new_cookie_hdr[offset] = ';';
-            offset++;
-            continue;
-          }
+         offset += sprintf (new_cookie_hdr + offset,
+                            " domain=%s;", 
+                            s5r->domain);
+         continue;          
         }
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    "Cookie domain invalid\n");        
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    _("Cookie domain `%s' supplied by server is invalid\n"),
+                   tok);
       }
       memcpy (new_cookie_hdr + offset, tok, strlen (tok));
       offset += strlen (tok);
-      new_cookie_hdr[offset] = ';';
-      offset++;
+      new_cookie_hdr[offset++] = ';';
     }
     hdr_val = new_cookie_hdr;
-
-#else
-    new_cookie_hdr = NULL;
-#endif
-  }
-  else
-  {
-    new_cookie_hdr = NULL;
   }
 
-#if 0
-  /* FIXME: adjust handling */
+  new_location = NULL;
   if (0 == strcasecmp (MHD_HTTP_HEADER_LOCATION, hdr_type))
   {
-    if (ctask->mhd->is_ssl)
-    {
-      sprintf (leho_host, "https://%s", ctask->leho);
-      sprintf (real_host, "https://%s", ctask->host);
-    }
-    else
-    {
-      sprintf (leho_host, "http://%s", ctask->leho);
-      sprintf (real_host, "http://%s", ctask->host);
-    }
-
-    if (0 == memcmp (leho_host, hdr_val, strlen (leho_host)))
+    char *leho_host;
+    
+    GNUNET_asprintf (&leho_host,
+                    (HTTPS_PORT != s5r->port)
+                    ? "http://%s"
+                    : "https://%s",
+                    s5r->leho);
+    if (0 == strncmp (leho_host, 
+                     hdr_val, 
+                     strlen (leho_host)))
     {
-      sprintf (new_location, "%s%s", real_host, hdr_val+strlen (leho_host));
+      GNUNET_asprintf (&new_location,
+                      "%s%s%s",
+                      (HTTPS_PORT != s5r->port)
+                      ? "http://"
+                      : "https://",
+                      s5r->domain,
+                      hdr_val + strlen (leho_host));
       hdr_val = new_location;
     }
+    GNUNET_free (leho_host);
   }
-#endif
   GNUNET_break (MHD_YES ==
                MHD_add_response_header (s5r->response,
                                         hdr_type,
                                         hdr_val));
   GNUNET_free (ndup);
   GNUNET_free_non_null (new_cookie_hdr);
+  GNUNET_free_non_null (new_location);
   return bytes;
 }
 
@@ -1767,9 +1764,8 @@ load_key_from_file (gnutls_x509_privkey_t key,
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 _("Unable to import private key from file `%s'\n"),
                keyfile);
-    GNUNET_break (0);
   }
-  GNUNET_free (key_data.data);
+  GNUNET_free_non_null (key_data.data);
   return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK;
 }
 
@@ -1795,9 +1791,8 @@ load_cert_from_file (gnutls_x509_crt_t crt,
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                _("Unable to import certificate %s\n"), certfile);
-    GNUNET_break (0);
   }
-  GNUNET_free (cert_data.data);
+  GNUNET_free_non_null (cert_data.data);
   return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK;
 }
 
@@ -2097,7 +2092,7 @@ signal_socks_success (struct Socks5Request *s5r)
 /**
  * Process GNS results for target domain.
  *
- * @param cls the ctask
+ * @param cls the `struct Socks5Request`
  * @param rd_count number of records returned
  * @param rd record data
  */