aboutsummaryrefslogtreecommitdiff
path: root/src/gns/gnunet-gns-proxy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gns/gnunet-gns-proxy.c')
-rw-r--r--src/gns/gnunet-gns-proxy.c503
1 files changed, 374 insertions, 129 deletions
diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c
index 02ebcf0f19..9a405c49bd 100644
--- a/src/gns/gnunet-gns-proxy.c
+++ b/src/gns/gnunet-gns-proxy.c
@@ -2,20 +2,18 @@
This file is part of GNUnet.
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
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- 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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Martin Schanzenbach
@@ -49,6 +47,15 @@
/**
+ * FIXME: GnuTLS right now sometimes rejects valid certs, so as a
+ * VERY temporary workaround we just WARN the user instead of
+ * dropping the page. THIS SHOULD NOT BE USED IN PRODUCTION,
+ * set to 1 in production!!! FIXME!!!
+ */
+#define FIXED_CERT_VALIDATION_BUG 0
+
+
+/**
* Default Socks5 listen port.
*/
#define GNUNET_GNS_PROXY_PORT 7777
@@ -106,7 +113,13 @@
* @param fun name of curl_easy-function that gave the error
* @param rc return code from curl
*/
-#define LOG_CURL_EASY(level,fun,rc) GNUNET_log(level, _("%s failed at %s:%d: `%s'\n"), fun, __FILE__, __LINE__, curl_easy_strerror (rc))
+#define LOG_CURL_EASY(level,fun,rc) \
+ GNUNET_log (level, \
+ _("%s failed at %s:%d: `%s'\n"), \
+ fun, \
+ __FILE__, \
+ __LINE__, \
+ curl_easy_strerror (rc))
/* *************** Socks protocol definitions (move to TUN?) ****************** */
@@ -626,6 +639,11 @@ struct Socks5Request
* Did we suspend MHD processing?
*/
int suspended;
+
+ /**
+ * Did we pause CURL processing?
+ */
+ int curl_paused;
};
@@ -636,7 +654,7 @@ struct Socks5Request
/**
* The port the proxy is running on (default 7777)
*/
-static unsigned long long port = GNUNET_GNS_PROXY_PORT;
+static uint16_t port = GNUNET_GNS_PROXY_PORT;
/**
* The CA file (pem) to use for the proxy CA
@@ -679,6 +697,11 @@ static CURLM *curl_multi;
static struct GNUNET_GNS_Handle *gns_handle;
/**
+ * Disable IPv6.
+ */
+static int disable_v6;
+
+/**
* DLL for http/https daemons
*/
static struct MhdHttpList *mhd_httpd_head;
@@ -763,21 +786,37 @@ cleanup_s5r (struct Socks5Request *s5r)
}
if ( (NULL != s5r->response) &&
(curl_failure_response != s5r->response) )
+ {
MHD_destroy_response (s5r->response);
+ s5r->response = NULL;
+ }
if (NULL != s5r->rtask)
+ {
GNUNET_SCHEDULER_cancel (s5r->rtask);
+ s5r->rtask = NULL;
+ }
if (NULL != s5r->timeout_task)
+ {
GNUNET_SCHEDULER_cancel (s5r->timeout_task);
+ s5r->timeout_task = NULL;
+ }
if (NULL != s5r->wtask)
+ {
GNUNET_SCHEDULER_cancel (s5r->wtask);
+ s5r->wtask = NULL;
+ }
if (NULL != s5r->gns_lookup)
+ {
GNUNET_GNS_lookup_with_tld_cancel (s5r->gns_lookup);
+ s5r->gns_lookup = NULL;
+ }
if (NULL != s5r->sock)
{
if (SOCKS5_SOCKET_WITH_MHD <= s5r->state)
GNUNET_NETWORK_socket_free_memory_only_ (s5r->sock);
else
GNUNET_NETWORK_socket_close (s5r->sock);
+ s5r->sock = NULL;
}
GNUNET_CONTAINER_DLL_remove (s5r_head,
s5r_tail,
@@ -823,7 +862,9 @@ mhd_content_cb (void *cls,
start the download, the IO buffer is still full
with upload data. */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Pausing MHD download, not yet ready for download\n");
+ "Pausing MHD download %s%s, not yet ready for download\n",
+ s5r->domain,
+ s5r->url);
return 0; /* not yet ready for data download */
}
bytes_to_copy = GNUNET_MIN (max,
@@ -832,12 +873,21 @@ mhd_content_cb (void *cls,
(SOCKS5_SOCKET_DOWNLOAD_DONE != s5r->state) )
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Pausing MHD download, no data available\n");
+ "Pausing MHD download %s%s, no data available\n",
+ s5r->domain,
+ s5r->url);
if (NULL != s5r->curl)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Continuing CURL interaction\n");
- curl_easy_pause (s5r->curl, CURLPAUSE_CONT);
+ "Continuing CURL interaction for %s%s\n",
+ s5r->domain,
+ s5r->url);
+ if (GNUNET_YES == s5r->curl_paused)
+ {
+ s5r->curl_paused = GNUNET_NO;
+ curl_easy_pause (s5r->curl,
+ CURLPAUSE_CONT);
+ }
curl_download_prepare ();
}
if (GNUNET_NO == s5r->suspended)
@@ -851,13 +901,17 @@ mhd_content_cb (void *cls,
(SOCKS5_SOCKET_DOWNLOAD_DONE == s5r->state) )
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Completed MHD download\n");
+ "Completed MHD download %s%s\n",
+ s5r->domain,
+ s5r->url);
return MHD_CONTENT_READER_END_OF_STREAM;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Writing %llu/%llu bytes\n",
+ "Writing %llu/%llu bytes to %s%s\n",
(unsigned long long) bytes_to_copy,
- (unsigned long long) s5r->io_len);
+ (unsigned long long) s5r->io_len,
+ s5r->domain,
+ s5r->url);
GNUNET_memcpy (buf,
s5r->io_buf,
bytes_to_copy);
@@ -865,10 +919,14 @@ mhd_content_cb (void *cls,
&s5r->io_buf[bytes_to_copy],
s5r->io_len - bytes_to_copy);
s5r->io_len -= bytes_to_copy;
- if (NULL != s5r->curl)
+ if ( (NULL != s5r->curl) &&
+ (GNUNET_YES == s5r->curl_paused) )
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Continuing CURL interaction\n");
+ "Continuing CURL interaction for %s%s\n",
+ s5r->domain,
+ s5r->url);
+ s5r->curl_paused = GNUNET_NO;
curl_easy_pause (s5r->curl,
CURLPAUSE_CONT);
}
@@ -911,8 +969,10 @@ check_ssl_certificate (struct Socks5Request *s5r)
tlsinfo->backend);
return GNUNET_SYSERR;
}
- chainp = gnutls_certificate_get_peers (tlsinfo->internals, &cert_list_size);
- if ( (! chainp) || (0 == cert_list_size) )
+ chainp = gnutls_certificate_get_peers (tlsinfo->internals,
+ &cert_list_size);
+ if ( (! chainp) ||
+ (0 == cert_list_size) )
return GNUNET_SYSERR;
size = sizeof (certdn);
@@ -1015,11 +1075,14 @@ check_ssl_certificate (struct Socks5Request *s5r)
name)))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("TLS certificate subject name (%s) does not match `%s'\n"),
+ _("TLS certificate subject name (%s) does not match `%s': %d\n"),
certdn,
- name);
+ name,
+ rc);
+#if FIXED_CERT_VALIDATION_BUG
gnutls_x509_crt_deinit (x509_cert);
return GNUNET_SYSERR;
+#endif
}
}
else
@@ -1075,15 +1138,17 @@ curl_check_hdr (void *buffer,
if (GNUNET_OK != check_ssl_certificate (s5r))
return 0;
}
-
- ndup = GNUNET_strndup (buffer, bytes);
- hdr_type = strtok (ndup, ":");
+ ndup = GNUNET_strndup (buffer,
+ bytes);
+ hdr_type = strtok (ndup,
+ ":");
if (NULL == hdr_type)
{
GNUNET_free (ndup);
return bytes;
}
- hdr_val = strtok (NULL, "");
+ hdr_val = strtok (NULL,
+ "");
if (NULL == hdr_val)
{
GNUNET_free (ndup);
@@ -1105,7 +1170,9 @@ curl_check_hdr (void *buffer,
domain_matched = GNUNET_NO; /* make sure we match domain at most once */
for (tok = strtok (hdr_val, ";"); NULL != tok; tok = strtok (NULL, ";"))
{
- if ( (0 == strncasecmp (tok, " domain", strlen (" domain"))) &&
+ if ( (0 == strncasecmp (tok,
+ " domain",
+ strlen (" domain"))) &&
(GNUNET_NO == domain_matched) )
{
domain_matched = GNUNET_YES;
@@ -1113,7 +1180,8 @@ curl_check_hdr (void *buffer,
if (strlen (cookie_domain) < strlen (s5r->leho))
{
delta_cdomain = strlen (s5r->leho) - strlen (cookie_domain);
- if (0 == strcasecmp (cookie_domain, s5r->leho + delta_cdomain))
+ if (0 == strcasecmp (cookie_domain,
+ s5r->leho + delta_cdomain))
{
offset += sprintf (new_cookie_hdr + offset,
" domain=%s;",
@@ -1121,7 +1189,8 @@ curl_check_hdr (void *buffer,
continue;
}
}
- else if (0 == strcmp (cookie_domain, s5r->leho))
+ else if (0 == strcmp (cookie_domain,
+ s5r->leho))
{
offset += sprintf (new_cookie_hdr + offset,
" domain=%s;",
@@ -1132,7 +1201,9 @@ curl_check_hdr (void *buffer,
_("Cookie domain `%s' supplied by server is invalid\n"),
tok);
}
- GNUNET_memcpy (new_cookie_hdr + offset, tok, strlen (tok));
+ GNUNET_memcpy (new_cookie_hdr + offset,
+ tok,
+ strlen (tok));
offset += strlen (tok);
new_cookie_hdr[offset++] = ';';
}
@@ -1140,7 +1211,14 @@ curl_check_hdr (void *buffer,
}
new_location = NULL;
- if (0 == strcasecmp (MHD_HTTP_HEADER_LOCATION, hdr_type))
+ if (0 == strcasecmp (MHD_HTTP_HEADER_TRANSFER_ENCODING,
+ hdr_type))
+ {
+ /* Ignore transfer encoding, set automatically by MHD if required */
+ goto cleanup;
+ }
+ if (0 == strcasecmp (MHD_HTTP_HEADER_LOCATION,
+ hdr_type))
{
char *leho_host;
@@ -1184,6 +1262,7 @@ curl_check_hdr (void *buffer,
s5r->header_tail,
header);
}
+ cleanup:
GNUNET_free (ndup);
GNUNET_free_non_null (new_cookie_hdr);
GNUNET_free_non_null (new_location);
@@ -1227,7 +1306,9 @@ create_mhd_response_from_s5r (struct Socks5Request *s5r)
s5r->domain,
s5r->url);
s5r->response_code = resp_code;
- s5r->response = MHD_create_response_from_callback ((-1 == content_length) ? MHD_SIZE_UNKNOWN : content_length,
+ s5r->response = MHD_create_response_from_callback ((-1 == content_length)
+ ? MHD_SIZE_UNKNOWN
+ : content_length,
IO_BUFFERSIZE,
&mhd_content_cb,
s5r,
@@ -1269,6 +1350,7 @@ create_mhd_response_from_s5r (struct Socks5Request *s5r)
return GNUNET_OK;
}
+
/**
* Handle response payload data from cURL. Copies it into our `io_buf` to make
* it available to MHD.
@@ -1288,6 +1370,12 @@ curl_download_cb (void *ptr,
struct Socks5Request *s5r = ctx;
size_t total = size * nmemb;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Receiving %ux%u bytes for `%s%s' from cURL\n",
+ (unsigned int) size,
+ (unsigned int) nmemb,
+ s5r->domain,
+ s5r->url);
if (NULL == s5r->response)
GNUNET_assert (GNUNET_OK ==
create_mhd_response_from_s5r (s5r));
@@ -1302,6 +1390,7 @@ curl_download_cb (void *ptr,
"Pausing CURL download `%s%s', waiting for UPLOAD to finish\n",
s5r->domain,
s5r->url);
+ s5r->curl_paused = GNUNET_YES;
return CURL_WRITEFUNC_PAUSE; /* not yet ready for data download */
}
if (sizeof (s5r->io_buf) - s5r->io_len < total)
@@ -1313,6 +1402,7 @@ curl_download_cb (void *ptr,
(unsigned long long) sizeof (s5r->io_buf),
(unsigned long long) s5r->io_len,
(unsigned long long) total);
+ s5r->curl_paused = GNUNET_YES;
return CURL_WRITEFUNC_PAUSE; /* not enough space */
}
GNUNET_memcpy (&s5r->io_buf[s5r->io_len],
@@ -1367,6 +1457,12 @@ curl_upload_cb (void *buf,
(SOCKS5_SOCKET_UPLOAD_DONE == s5r->state) )
{
s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED;
+ if (GNUNET_YES == s5r->curl_paused)
+ {
+ s5r->curl_paused = GNUNET_NO;
+ curl_easy_pause (s5r->curl,
+ CURLPAUSE_CONT);
+ }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Completed CURL UPLOAD %s%s\n",
s5r->domain,
@@ -1381,7 +1477,9 @@ curl_upload_cb (void *buf,
}
to_copy = GNUNET_MIN (s5r->io_len,
len);
- GNUNET_memcpy (buf, s5r->io_buf, to_copy);
+ GNUNET_memcpy (buf,
+ s5r->io_buf,
+ to_copy);
memmove (s5r->io_buf,
&s5r->io_buf[to_copy],
s5r->io_len - to_copy);
@@ -1445,20 +1543,28 @@ curl_download_prepare ()
return;
}
to = -1;
- GNUNET_break (CURLM_OK == curl_multi_timeout (curl_multi, &to));
+ GNUNET_break (CURLM_OK ==
+ curl_multi_timeout (curl_multi,
+ &to));
if (-1 == to)
rtime = GNUNET_TIME_UNIT_FOREVER_REL;
else
- rtime = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, to);
+ rtime = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+ to);
if (-1 != max)
{
grs = GNUNET_NETWORK_fdset_create ();
gws = GNUNET_NETWORK_fdset_create ();
- GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
- GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
+ GNUNET_NETWORK_fdset_copy_native (grs,
+ &rs,
+ max + 1);
+ GNUNET_NETWORK_fdset_copy_native (gws,
+ &ws,
+ max + 1);
curl_download_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
rtime,
- grs, gws,
+ grs,
+ gws,
&curl_task_download,
curl_multi);
GNUNET_NETWORK_fdset_destroy (gws);
@@ -1495,6 +1601,9 @@ curl_task_download (void *cls)
running = 0;
mret = curl_multi_perform (curl_multi,
&running);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Checking CURL multi status: %d\n",
+ mret);
while (NULL != (msg = curl_multi_info_read (curl_multi,
&msgnum)))
{
@@ -1527,7 +1636,12 @@ curl_task_download (void *cls)
GNUNET_assert (GNUNET_OK ==
create_mhd_response_from_s5r (s5r));
}
- s5r->state = SOCKS5_SOCKET_DOWNLOAD_DONE;
+ s5r->state = SOCKS5_SOCKET_DOWNLOAD_DONE;
+ if (GNUNET_YES == s5r->suspended)
+ {
+ MHD_resume_connection (s5r->con);
+ s5r->suspended = GNUNET_NO;
+ }
run_mhd_now (s5r->hd);
break;
default:
@@ -1538,6 +1652,11 @@ curl_task_download (void *cls)
curl_easy_strerror (msg->data.result));
/* FIXME: indicate error somehow? close MHD connection badly as well? */
s5r->state = SOCKS5_SOCKET_DOWNLOAD_DONE;
+ if (GNUNET_YES == s5r->suspended)
+ {
+ MHD_resume_connection (s5r->con);
+ s5r->suspended = GNUNET_NO;
+ }
run_mhd_now (s5r->hd);
break;
}
@@ -1600,12 +1719,15 @@ con_val_iter (void *cls,
struct Socks5Request *s5r = cls;
char *hdr;
- if ( (0 == strcasecmp (MHD_HTTP_HEADER_HOST, key)) &&
+ if ( (0 == strcasecmp (MHD_HTTP_HEADER_HOST,
+ key)) &&
(NULL != s5r->leho) )
value = s5r->leho;
- if (0 == strcasecmp (MHD_HTTP_HEADER_CONTENT_LENGTH, key))
+ if (0 == strcasecmp (MHD_HTTP_HEADER_CONTENT_LENGTH,
+ key))
return MHD_YES;
- if (0 == strcasecmp (MHD_HTTP_HEADER_ACCEPT_ENCODING, key))
+ if (0 == strcasecmp (MHD_HTTP_HEADER_ACCEPT_ENCODING,
+ key))
return MHD_YES;
GNUNET_asprintf (&hdr,
"%s: %s",
@@ -1670,7 +1792,7 @@ create_response (void *cls,
return MHD_NO;
}
s5r->con = con;
- //Fresh connection.
+ /* Fresh connection. */
if (SOCKS5_SOCKET_WITH_MHD == s5r->state)
{
/* first time here, initialize curl handle */
@@ -1726,21 +1848,40 @@ create_response (void *cls,
return MHD_queue_response (con,
MHD_HTTP_INTERNAL_SERVER_ERROR,
curl_failure_response);
- curl_easy_setopt (s5r->curl, CURLOPT_HEADERFUNCTION, &curl_check_hdr);
- curl_easy_setopt (s5r->curl, CURLOPT_HEADERDATA, s5r);
- curl_easy_setopt (s5r->curl, CURLOPT_FOLLOWLOCATION, 0);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_HEADERFUNCTION,
+ &curl_check_hdr);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_HEADERDATA,
+ s5r);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_FOLLOWLOCATION,
+ 0);
if (s5r->is_gns)
curl_easy_setopt (s5r->curl,
CURLOPT_IPRESOLVE,
CURL_IPRESOLVE_V4);
- curl_easy_setopt (s5r->curl, CURLOPT_CONNECTTIMEOUT, 600L);
- curl_easy_setopt (s5r->curl, CURLOPT_TIMEOUT, 600L);
- curl_easy_setopt (s5r->curl, CURLOPT_NOSIGNAL, 1L);
- curl_easy_setopt (s5r->curl, CURLOPT_HTTP_CONTENT_DECODING, 0);
- curl_easy_setopt (s5r->curl, CURLOPT_HTTP_TRANSFER_DECODING, 0);
- curl_easy_setopt (s5r->curl, CURLOPT_NOSIGNAL, 1L);
- curl_easy_setopt (s5r->curl, CURLOPT_PRIVATE, s5r);
- curl_easy_setopt (s5r->curl, CURLOPT_VERBOSE, 0L);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_CONNECTTIMEOUT,
+ 600L);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_TIMEOUT,
+ 600L);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_NOSIGNAL,
+ 1L);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_HTTP_CONTENT_DECODING,
+ 0);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_NOSIGNAL,
+ 1L);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_PRIVATE,
+ s5r);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_VERBOSE,
+ 0L);
/**
* Pre-populate cache to resolve Hostname.
* This is necessary as the DNS name in the CURLOPT_URL is used
@@ -1796,11 +1937,22 @@ create_response (void *cls,
MHD_HTTP_METHOD_PUT))
{
s5r->state = SOCKS5_SOCKET_UPLOAD_STARTED;
- curl_easy_setopt (s5r->curl, CURLOPT_UPLOAD, 1L);
- curl_easy_setopt (s5r->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb);
- curl_easy_setopt (s5r->curl, CURLOPT_WRITEDATA, s5r);
- curl_easy_setopt (s5r->curl, CURLOPT_READFUNCTION, &curl_upload_cb);
- curl_easy_setopt (s5r->curl, CURLOPT_READDATA, s5r);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_UPLOAD,
+ 1L);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_WRITEFUNCTION,
+ &curl_download_cb);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_WRITEDATA,
+ s5r);
+ GNUNET_assert (CURLE_OK ==
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_READFUNCTION,
+ &curl_upload_cb));
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_READDATA,
+ s5r);
{
const char *us;
long upload_size;
@@ -1822,11 +1974,21 @@ create_response (void *cls,
else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_POST))
{
s5r->state = SOCKS5_SOCKET_UPLOAD_STARTED;
- curl_easy_setopt (s5r->curl, CURLOPT_POST, 1L);
- curl_easy_setopt (s5r->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb);
- curl_easy_setopt (s5r->curl, CURLOPT_WRITEDATA, s5r);
- curl_easy_setopt (s5r->curl, CURLOPT_READFUNCTION, &curl_upload_cb);
- curl_easy_setopt (s5r->curl, CURLOPT_READDATA, s5r);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_POST,
+ 1L);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_WRITEFUNCTION,
+ &curl_download_cb);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_WRITEDATA,
+ s5r);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_READFUNCTION,
+ &curl_upload_cb);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_READDATA,
+ s5r);
{
const char *us;
long upload_size;
@@ -1834,7 +1996,7 @@ create_response (void *cls,
us = MHD_lookup_connection_value (con,
MHD_HEADER_KIND,
MHD_HTTP_HEADER_CONTENT_LENGTH);
- if ( (1 == sscanf (us,
+ if ( (NULL != us) && (1 == sscanf (us,
"%ld",
&upload_size)) &&
(upload_size >= 0) )
@@ -1842,25 +2004,42 @@ create_response (void *cls,
curl_easy_setopt (s5r->curl,
CURLOPT_INFILESIZE,
upload_size);
+ } else {
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_INFILESIZE,
+ upload_size);
}
}
}
- else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_HEAD))
+ else if (0 == strcasecmp (meth,
+ MHD_HTTP_METHOD_HEAD))
{
s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED;
- curl_easy_setopt (s5r->curl, CURLOPT_NOBODY, 1L);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_NOBODY,
+ 1L);
}
- else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_OPTIONS))
+ else if (0 == strcasecmp (meth,
+ MHD_HTTP_METHOD_OPTIONS))
{
s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED;
- curl_easy_setopt (s5r->curl, CURLOPT_CUSTOMREQUEST, "OPTIONS");
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_CUSTOMREQUEST,
+ "OPTIONS");
}
- else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_GET))
+ else if (0 == strcasecmp (meth,
+ MHD_HTTP_METHOD_GET))
{
s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED;
- curl_easy_setopt (s5r->curl, CURLOPT_HTTPGET, 1L);
- curl_easy_setopt (s5r->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb);
- curl_easy_setopt (s5r->curl, CURLOPT_WRITEDATA, s5r);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_HTTPGET,
+ 1L);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_WRITEFUNCTION,
+ &curl_download_cb);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_WRITEDATA,
+ s5r);
}
else
{
@@ -1874,31 +2053,47 @@ create_response (void *cls,
if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_0))
{
- curl_easy_setopt (s5r->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_HTTP_VERSION,
+ CURL_HTTP_VERSION_1_0);
}
else if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_1))
{
- curl_easy_setopt (s5r->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_HTTP_VERSION,
+ CURL_HTTP_VERSION_1_1);
}
else
{
- curl_easy_setopt (s5r->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_NONE);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_HTTP_VERSION,
+ CURL_HTTP_VERSION_NONE);
}
if (HTTPS_PORT == s5r->port)
{
- curl_easy_setopt (s5r->curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_USE_SSL,
+ CURLUSESSL_ALL);
if (NULL != s5r->dane_data)
- curl_easy_setopt (s5r->curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_SSL_VERIFYPEER,
+ 0L);
else
- curl_easy_setopt (s5r->curl, CURLOPT_SSL_VERIFYPEER, 1L);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_SSL_VERIFYPEER,
+ 1L);
/* Disable cURL checking the hostname, as we will check ourselves
as only we have the domain name or the LEHO or the DANE record */
- curl_easy_setopt (s5r->curl, CURLOPT_SSL_VERIFYHOST, 0L);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_SSL_VERIFYHOST,
+ 0L);
}
else
{
- curl_easy_setopt (s5r->curl, CURLOPT_USE_SSL, CURLUSESSL_NONE);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_USE_SSL,
+ CURLUSESSL_NONE);
}
if (CURLM_OK !=
@@ -1931,7 +2126,9 @@ create_response (void *cls,
/* FIXME: This must be set or a header with Transfer-Encoding: chunked. Else
* upload callback is not called!
*/
- curl_easy_setopt (s5r->curl, CURLOPT_POSTFIELDSIZE, *upload_data_size);
+ curl_easy_setopt (s5r->curl,
+ CURLOPT_POSTFIELDSIZE,
+ *upload_data_size);
left = GNUNET_MIN (*upload_data_size,
sizeof (s5r->io_buf) - s5r->io_len);
@@ -1941,8 +2138,12 @@ create_response (void *cls,
s5r->io_len += left;
*upload_data_size -= left;
GNUNET_assert (NULL != s5r->curl);
- curl_easy_pause (s5r->curl,
- CURLPAUSE_CONT);
+ if (GNUNET_YES == s5r->curl_paused)
+ {
+ s5r->curl_paused = GNUNET_NO;
+ curl_easy_pause (s5r->curl,
+ CURLPAUSE_CONT);
+ }
return MHD_YES;
}
if (SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state)
@@ -2320,8 +2521,10 @@ load_file (const char* filename,
uint64_t fsize;
if (GNUNET_OK !=
- GNUNET_DISK_file_size (filename, &fsize,
- GNUNET_YES, GNUNET_YES))
+ GNUNET_DISK_file_size (filename,
+ &fsize,
+ GNUNET_YES,
+ GNUNET_YES))
return NULL;
if (fsize > MAX_PEM_SIZE)
return NULL;
@@ -2353,7 +2556,8 @@ load_key_from_file (gnutls_x509_privkey_t key,
gnutls_datum_t key_data;
int ret;
- key_data.data = load_file (keyfile, &key_data.size);
+ key_data.data = load_file (keyfile,
+ &key_data.size);
if (NULL == key_data.data)
return GNUNET_SYSERR;
ret = gnutls_x509_privkey_import (key, &key_data,
@@ -2383,15 +2587,18 @@ load_cert_from_file (gnutls_x509_crt_t crt,
gnutls_datum_t cert_data;
int ret;
- cert_data.data = load_file (certfile, &cert_data.size);
+ cert_data.data = load_file (certfile,
+ &cert_data.size);
if (NULL == cert_data.data)
return GNUNET_SYSERR;
- ret = gnutls_x509_crt_import (crt, &cert_data,
+ ret = gnutls_x509_crt_import (crt,
+ &cert_data,
GNUTLS_X509_FMT_PEM);
if (GNUTLS_E_SUCCESS != ret)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to import certificate %s\n"), certfile);
+ _("Unable to import certificate from `%s'\n"),
+ certfile);
}
GNUNET_free_non_null (cert_data.data);
return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK;
@@ -2421,14 +2628,27 @@ generate_gns_certificate (const char *name)
GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_init (&request));
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, "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,
- 0, name, strlen (name));
- GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_set_version (request, 3));
- gnutls_rnd (GNUTLS_RND_NONCE, &serial, sizeof (serial));
+ gnutls_x509_crt_set_dn_by_oid (request,
+ GNUTLS_OID_X520_COUNTRY_NAME,
+ 0,
+ "ZZ",
+ strlen ("ZZ"));
+ gnutls_x509_crt_set_dn_by_oid (request,
+ GNUTLS_OID_X520_ORGANIZATION_NAME,
+ 0,
+ "GNU Name System",
+ strlen ("GNU Name System"));
+ gnutls_x509_crt_set_dn_by_oid (request,
+ GNUTLS_OID_X520_COMMON_NAME,
+ 0,
+ name,
+ strlen (name));
+ GNUNET_break (GNUTLS_E_SUCCESS ==
+ gnutls_x509_crt_set_version (request,
+ 3));
+ gnutls_rnd (GNUTLS_RND_NONCE,
+ &serial,
+ sizeof (serial));
gnutls_x509_crt_set_serial (request,
&serial,
sizeof (serial));
@@ -2442,15 +2662,21 @@ generate_gns_certificate (const char *name)
etime = mktime (tm_data);
gnutls_x509_crt_set_expiration_time (request,
etime);
- gnutls_x509_crt_sign (request,
- proxy_ca.cert,
- proxy_ca.key);
+ gnutls_x509_crt_sign2 (request,
+ proxy_ca.cert,
+ proxy_ca.key,
+ GNUTLS_DIG_SHA512,
+ 0);
key_buf_size = sizeof (pgc->key);
cert_buf_size = sizeof (pgc->cert);
- gnutls_x509_crt_export (request, GNUTLS_X509_FMT_PEM,
- pgc->cert, &cert_buf_size);
- gnutls_x509_privkey_export (proxy_ca.key, GNUTLS_X509_FMT_PEM,
- pgc->key, &key_buf_size);
+ gnutls_x509_crt_export (request,
+ GNUTLS_X509_FMT_PEM,
+ pgc->cert,
+ &cert_buf_size);
+ gnutls_x509_privkey_export (proxy_ca.key,
+ GNUTLS_X509_FMT_PEM,
+ pgc->key,
+ &key_buf_size);
gnutls_x509_crt_deinit (request);
return pgc;
}
@@ -2789,8 +3015,10 @@ handle_gns_result (void *cls,
}
if (GNUNET_YES == got_ip)
break;
+ if (GNUNET_YES == disable_v6)
+ break;
if (GNUNET_OK !=
- GNUNET_NETWORK_test_pf (PF_INET))
+ GNUNET_NETWORK_test_pf (PF_INET6))
break;
/* FIXME: allow user to disable IPv6 per configuration option... */
got_ip = GNUNET_YES;
@@ -2891,7 +3119,8 @@ do_s5r_read (void *cls)
s5r->rtask = NULL;
tc = GNUNET_SCHEDULER_get_task_context ();
if ( (NULL != tc->read_ready) &&
- (GNUNET_NETWORK_fdset_isset (tc->read_ready, s5r->sock)) )
+ (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+ s5r->sock)) )
{
rlen = GNUNET_NETWORK_socket_recv (s5r->sock,
&s5r->rbuf[s5r->rbuf_len],
@@ -3017,7 +3246,8 @@ do_s5r_read (void *cls)
s5r->domain = GNUNET_strndup (dom_name,
*dom_len);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Requested connection is to %s:%d\n",
+ "Requested connection is to http%s://%s:%d\n",
+ (HTTPS_PORT == s5r->port) ? "s" : "",
s5r->domain,
ntohs (*port));
s5r->state = SOCKS5_RESOLVING;
@@ -3088,17 +3318,22 @@ do_accept (void *cls)
if (lsock == lsock4)
ltask4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
lsock,
- &do_accept, lsock);
+ &do_accept,
+ lsock);
else if (lsock == lsock6)
ltask6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
lsock,
- &do_accept, lsock);
+ &do_accept,
+ lsock);
else
GNUNET_assert (0);
- s = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL);
+ s = GNUNET_NETWORK_socket_accept (lsock,
+ NULL,
+ NULL);
if (NULL == s)
{
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "accept");
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+ "accept");
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -3111,7 +3346,8 @@ do_accept (void *cls)
s5r->state = SOCKS5_INIT;
s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
s5r->sock,
- &do_s5r_read, s5r);
+ &do_s5r_read,
+ s5r);
}
@@ -3208,7 +3444,8 @@ bind_v4 ()
if (NULL == ls)
return NULL;
if (GNUNET_OK !=
- GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa4,
+ GNUNET_NETWORK_socket_bind (ls,
+ (const struct sockaddr *) &sa4,
sizeof (sa4)))
{
eno = errno;
@@ -3244,7 +3481,8 @@ bind_v6 ()
if (NULL == ls)
return NULL;
if (GNUNET_OK !=
- GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa6,
+ GNUNET_NETWORK_socket_bind (ls,
+ (const struct sockaddr *) &sa6,
sizeof (sa6)))
{
eno = errno;
@@ -3299,7 +3537,8 @@ run (void *cls,
cafile = cafile_cfg;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Using %s as CA\n", cafile);
+ "Using `%s' as CA\n",
+ cafile);
gnutls_global_init ();
gnutls_x509_crt_init (&proxy_ca.cert);
@@ -3399,8 +3638,8 @@ run (void *cls,
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Proxy listens on port %llu\n",
- port);
+ "Proxy listens on port %u\n",
+ (unsigned int) port);
/* start MHD daemon for HTTP */
hd = GNUNET_new (struct MhdHttpList);
@@ -3434,19 +3673,24 @@ run (void *cls,
* @return 0 ok, 1 on error
*/
int
-main (int argc, char *const *argv)
+main (int argc,
+ char *const *argv)
{
struct GNUNET_GETOPT_CommandLineOption options[] = {
- GNUNET_GETOPT_option_ulong ('p',
- "port",
- NULL,
- gettext_noop ("listen on specified port (default: 7777)"),
- &port),
+ GNUNET_GETOPT_option_uint16 ('p',
+ "port",
+ NULL,
+ gettext_noop ("listen on specified port (default: 7777)"),
+ &port),
GNUNET_GETOPT_option_string ('a',
"authority",
NULL,
gettext_noop ("pem file to use as CA"),
&cafile_opt),
+ GNUNET_GETOPT_option_flag ('6',
+ "disable-ivp6",
+ gettext_noop ("disable use of IPv6"),
+ &disable_v6),
GNUNET_GETOPT_OPTION_END
};
@@ -3455,8 +3699,9 @@ main (int argc, char *const *argv)
"</head><body>cURL fail</body></html>";
int ret;
- if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv,
- &argc, &argv))
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_get_utf8_args (argc, argv,
+ &argc, &argv))
return 2;
GNUNET_log_setup ("gnunet-gns-proxy",
"WARNING",