/*
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
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
*/
#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>
/**
* The task ID
*/
- GNUNET_SCHEDULER_TaskIdentifier httpd_task;
+ struct GNUNET_SCHEDULER_Task *httpd_task;
/**
* is this an ssl daemon?
SOCKS5_SOCKET_WITH_MHD,
/**
- * We've finished receiving upload data from MHD.
+ * We've started receiving upload data from MHD.
*/
SOCKS5_SOCKET_UPLOAD_STARTED,
};
+/**
+ * A header list
+ */
+struct HttpResponseHeader
+{
+ /**
+ * DLL
+ */
+ struct HttpResponseHeader *next;
+
+ /**
+ * DLL
+ */
+ struct HttpResponseHeader *prev;
+
+ /**
+ * Header type
+ */
+ char *type;
+
+ /**
+ * Header value
+ */
+ char *value;
+};
/**
* A structure for socks requests
/**
* 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
*/
struct curl_slist *headers;
+ /**
+ * DNS->IP mappings resolved through GNS
+ */
+ struct curl_slist *hosts;
+
/**
* HTTP response code to give to MHD for the response.
*/
*/
uint16_t port;
+ /**
+ * Headers from response
+ */
+ struct HttpResponseHeader *header_head;
+
+ /**
+ * Headers from response
+ */
+ struct HttpResponseHeader *header_tail;
+
+ /**
+ * SSL Certificate status
+ */
+ int ssl_checked;
};
/**
* The port the proxy is running on (default 7777)
*/
-static unsigned long port = GNUNET_GNS_PROXY_PORT;
+static unsigned long long port = GNUNET_GNS_PROXY_PORT;
/**
* The CA file (pem) to use for the proxy CA
/**
* 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
*/
static struct GNUNET_CRYPTO_EcdsaPublicKey local_gns_zone;
-/**
- * The users local shorten zone
- */
-static struct GNUNET_CRYPTO_EcdsaPrivateKey local_shorten_zone;
-
-/**
- * Is shortening enabled?
- */
-static int do_shorten;
-
/**
* The CA for SSL certificate generation
*/
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);
/* ************************* HTTP handling with cURL *********************** */
+static void
+curl_download_prepare ();
/**
* Callback for MHD response generation. This function is called from
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Pausing MHD download, no data available\n");
+ if (NULL != s5r->curl)
+ {
+ curl_easy_pause (s5r->curl, CURLPAUSE_CONT);
+ curl_download_prepare ();
+ }
return 0; /* more data later */
}
if ( (0 == bytes_to_copy) &&
"Completed MHD download\n");
return MHD_CONTENT_READER_END_OF_STREAM;
}
- memcpy (buf, s5r->io_buf, bytes_to_copy);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Writing %lu/%lu bytes\n", bytes_to_copy, s5r->io_len);
+ GNUNET_memcpy (buf, s5r->io_buf, bytes_to_copy);
memmove (s5r->io_buf,
&s5r->io_buf[bytes_to_copy],
s5r->io_len - bytes_to_copy);
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;
+ s5r->ssl_checked = GNUNET_YES;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Checking SSL certificate\n");
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;
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)))
curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls)
{
struct Socks5Request *s5r = cls;
+ struct HttpResponseHeader *header;
size_t bytes = size * nmemb;
char *ndup;
const char *hdr_type;
const char *cookie_domain;
char *hdr_val;
- long resp_code;
char *new_cookie_hdr;
char *new_location;
size_t offset;
int domain_matched;
char *tok;
- if (NULL == s5r->response)
+ /* first, check SSL certificate */
+ if ((GNUNET_YES != s5r->ssl_checked) &&
+ (HTTPS_PORT == s5r->port))
{
- /* first, check SSL certificate */
- if ( (HTTPS_PORT == s5r->port) &&
- (GNUNET_OK != check_ssl_certificate (s5r)) )
- return 0;
-
- GNUNET_break (CURLE_OK ==
- curl_easy_getinfo (s5r->curl,
- CURLINFO_RESPONSE_CODE,
- &resp_code));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Creating MHD response with code %d\n",
- (int) resp_code);
- s5r->response_code = resp_code;
- s5r->response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
- IO_BUFFERSIZE,
- &mhd_content_cb,
- s5r,
- NULL);
- if (NULL != s5r->leho)
- {
- char *cors_hdr;
-
- GNUNET_asprintf (&cors_hdr,
- (HTTPS_PORT == s5r->port)
- ? "https://%s"
- : "http://%s",
- s5r->leho);
-
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (s5r->response,
- MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
- cors_hdr));
- GNUNET_free (cors_hdr);
- }
- /* force connection to be closed after each request, as we
- do not support HTTP pipelining */
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (s5r->response,
- MHD_HTTP_HEADER_CONNECTION,
- "close"));
+ if (GNUNET_OK != check_ssl_certificate (s5r))
+ return 0;
}
ndup = GNUNET_strndup (buffer, bytes);
new_cookie_hdr = NULL;
if ( (NULL != s5r->leho) &&
(0 == strcasecmp (hdr_type,
- MHD_HTTP_HEADER_SET_COOKIE)) )
+ MHD_HTTP_HEADER_SET_COOKIE)) )
{
new_cookie_hdr = GNUNET_malloc (strlen (hdr_val) +
- strlen (s5r->domain) + 1);
+ 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 == strncasecmp (tok, " domain", strlen (" domain"))) &&
- (GNUNET_NO == domain_matched) )
+ (GNUNET_NO == domain_matched) )
{
- domain_matched = GNUNET_YES;
+ domain_matched = GNUNET_YES;
cookie_domain = tok + strlen (" domain") + 1;
if (strlen (cookie_domain) < strlen (s5r->leho))
{
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);
+ " domain=%s;",
+ s5r->domain);
continue;
}
}
else if (0 == strcmp (cookie_domain, s5r->leho))
{
- offset += sprintf (new_cookie_hdr + offset,
- " domain=%s;",
- s5r->domain);
- continue;
+ offset += sprintf (new_cookie_hdr + offset,
+ " domain=%s;",
+ s5r->domain);
+ continue;
}
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
_("Cookie domain `%s' supplied by server is invalid\n"),
- tok);
+ tok);
}
- memcpy (new_cookie_hdr + offset, tok, strlen (tok));
+ GNUNET_memcpy (new_cookie_hdr + offset, tok, strlen (tok));
offset += strlen (tok);
new_cookie_hdr[offset++] = ';';
}
char *leho_host;
GNUNET_asprintf (&leho_host,
- (HTTPS_PORT != s5r->port)
- ? "http://%s"
- : "https://%s",
- s5r->leho);
+ (HTTPS_PORT != s5r->port)
+ ? "http://%s"
+ : "https://%s",
+ s5r->leho);
if (0 == strncmp (leho_host,
- hdr_val,
- strlen (leho_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));
+ "%s%s%s",
+ (HTTPS_PORT != s5r->port)
+ ? "http://"
+ : "https://",
+ s5r->domain,
+ hdr_val + strlen (leho_host));
hdr_val = new_location;
}
GNUNET_free (leho_host);
*tok = '\0';
if (NULL != (tok = strchr (hdr_val, '\t')))
*tok = '\0';
- if (0 != strlen (hdr_val))
+ if (0 != strlen (hdr_val)) /* Rely in MHD to set those */
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Adding header %s: %s to MHD response\n",
- hdr_type,
- hdr_val);
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (s5r->response,
- hdr_type,
- hdr_val));
+ "Adding header %s: %s to MHD response\n",
+ hdr_type,
+ hdr_val);
+ header = GNUNET_new (struct HttpResponseHeader);
+ header->type = GNUNET_strndup (hdr_type, strlen (hdr_type));
+ header->value = GNUNET_strndup (hdr_val, strlen (hdr_val));
+ GNUNET_CONTAINER_DLL_insert (s5r->header_head,
+ s5r->header_tail,
+ header);
}
GNUNET_free (ndup);
GNUNET_free_non_null (new_cookie_hdr);
return bytes;
}
+static int
+create_mhd_response_from_s5r (struct Socks5Request *s5r)
+{
+ long resp_code;
+ double content_length;
+ struct HttpResponseHeader *header;
+
+ if (NULL != s5r->response)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Response already set!\n");
+ return GNUNET_SYSERR;
+ }
+
+ GNUNET_break (CURLE_OK ==
+ curl_easy_getinfo (s5r->curl,
+ CURLINFO_RESPONSE_CODE,
+ &resp_code));
+ GNUNET_break (CURLE_OK ==
+ curl_easy_getinfo (s5r->curl,
+ CURLINFO_CONTENT_LENGTH_DOWNLOAD,
+ &content_length));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Creating MHD response with code %d and size %d\n",
+ (int) resp_code, (int) content_length);
+ s5r->response_code = resp_code;
+ s5r->response = MHD_create_response_from_callback ((-1 == content_length) ? MHD_SIZE_UNKNOWN : content_length,
+ IO_BUFFERSIZE,
+ &mhd_content_cb,
+ s5r,
+ NULL);
+ for (header = s5r->header_head; NULL != header; header = header->next)
+ {
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (s5r->response,
+ header->type,
+ header->value));
+
+ }
+ if (NULL != s5r->leho)
+ {
+ char *cors_hdr;
+
+ GNUNET_asprintf (&cors_hdr,
+ (HTTPS_PORT == s5r->port)
+ ? "https://%s"
+ : "http://%s",
+ s5r->leho);
+
+ GNUNET_break (MHD_YES ==
+ MHD_add_response_header (s5r->response,
+ MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
+ cors_hdr));
+ GNUNET_free (cors_hdr);
+ }
+ /* force connection to be closed after each request, as we
+ do not support HTTP pipelining (yet, FIXME!) */
+ /*GNUNET_break (MHD_YES ==
+ MHD_add_response_header (s5r->response,
+ MHD_HTTP_HEADER_CONNECTION,
+ "close"));*/
+ return GNUNET_OK;
+}
/**
* Handle response payload data from cURL. Copies it into our `io_buf` to make
struct Socks5Request *s5r = ctx;
size_t total = size * nmemb;
+ if (NULL == s5r->response)
+ GNUNET_assert (GNUNET_OK == create_mhd_response_from_s5r (s5r));
+
if ( (SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state) ||
(SOCKS5_SOCKET_UPLOAD_DONE == s5r->state) )
{
start the download, the IO buffer is still full
with upload data. */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Pausing CURL download, waiting for UPLOAD to finish\n");
+ "Pausing CURL download, waiting for UPLOAD to finish\n");
return CURL_WRITEFUNC_PAUSE; /* not yet ready for data download */
}
if (sizeof (s5r->io_buf) - s5r->io_len < total)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Pausing CURL download, not enough space\n");
+ "Pausing CURL download, not enough space %lu %lu %lu\n", sizeof (s5r->io_buf),
+ s5r->io_len, total);
return CURL_WRITEFUNC_PAUSE; /* not enough space */
}
- memcpy (&s5r->io_buf[s5r->io_len],
- ptr,
- total);
+ GNUNET_memcpy (&s5r->io_buf[s5r->io_len],
+ ptr,
+ total);
s5r->io_len += total;
if (s5r->io_len == total)
run_mhd_now (s5r->hd);
(SOCKS5_SOCKET_UPLOAD_DONE != s5r->state) )
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Pausing CURL UPLOAD, need more data\n");
+ "Pausing CURL UPLOAD, need more data\n");
return CURL_READFUNC_PAUSE;
}
if ( (0 == s5r->io_len) &&
{
s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Completed CURL UPLOAD\n");
+ "Completed CURL UPLOAD\n");
return 0; /* upload finished, can now download */
}
- if ( (SOCKS5_SOCKET_UPLOAD_STARTED != s5r->state) ||
+ if ( (SOCKS5_SOCKET_UPLOAD_STARTED != s5r->state) &&
(SOCKS5_SOCKET_UPLOAD_DONE != s5r->state) )
{
GNUNET_break (0);
return CURL_READFUNC_ABORT;
}
to_copy = GNUNET_MIN (s5r->io_len,
- len);
- memcpy (buf, s5r->io_buf, to_copy);
+ len);
+ GNUNET_memcpy (buf, s5r->io_buf, to_copy);
memmove (s5r->io_buf,
- &s5r->io_buf[to_copy],
- s5r->io_len - to_copy);
+ &s5r->io_buf[to_copy],
+ s5r->io_len - to_copy);
s5r->io_len -= to_copy;
if (s5r->io_len + to_copy == sizeof (s5r->io_buf))
run_mhd_now (s5r->hd); /* got more space for upload now */
* 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);
/**
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);
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,
- &curl_task_download, curl_multi);
+ rtime,
+ grs, gws,
+ &curl_task_download, curl_multi);
GNUNET_NETWORK_fdset_destroy (gws);
GNUNET_NETWORK_fdset_destroy (grs);
}
* 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;
CURLMcode mret;
struct Socks5Request *s5r;
- curl_download_task = GNUNET_SCHEDULER_NO_TASK;
+ curl_download_task = NULL;
do
{
running = 0;
while (NULL != (msg = curl_multi_info_read (curl_multi, &msgnum)))
{
GNUNET_break (CURLE_OK ==
- curl_easy_getinfo (msg->easy_handle,
- CURLINFO_PRIVATE,
- &s5r));
+ curl_easy_getinfo (msg->easy_handle,
+ CURLINFO_PRIVATE,
+ (char **) &s5r ));
if (NULL == s5r)
{
- GNUNET_break (0);
- continue;
+ GNUNET_break (0);
+ continue;
}
switch (msg->msg)
{
- case CURLMSG_NONE:
- /* documentation says this is not used */
- GNUNET_break (0);
- break;
- case CURLMSG_DONE:
- switch (msg->data.result)
- {
- case CURLE_OK:
- case CURLE_GOT_NOTHING:
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "CURL download completed.\n");
- s5r->state = SOCKS5_SOCKET_DOWNLOAD_DONE;
- run_mhd_now (s5r->hd);
- break;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Download curl failed: %s\n",
- curl_easy_strerror (msg->data.result));
- /* FIXME: indicate error somehow? close MHD connection badly as well? */
- s5r->state = SOCKS5_SOCKET_DOWNLOAD_DONE;
- run_mhd_now (s5r->hd);
- break;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Cleaning up cURL handle\n");
- curl_multi_remove_handle (curl_multi, s5r->curl);
- curl_easy_cleanup (s5r->curl);
- s5r->curl = NULL;
- if (NULL == s5r->response)
- s5r->response = curl_failure_response;
- break;
- case CURLMSG_LAST:
- /* documentation says this is not used */
- GNUNET_break (0);
- break;
- default:
- /* unexpected status code */
- GNUNET_break (0);
- break;
+ case CURLMSG_NONE:
+ /* documentation says this is not used */
+ GNUNET_break (0);
+ break;
+ case CURLMSG_DONE:
+ switch (msg->data.result)
+ {
+ case CURLE_OK:
+ case CURLE_GOT_NOTHING:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "CURL download completed.\n");
+ if (NULL == s5r->response)
+ GNUNET_assert (GNUNET_OK == create_mhd_response_from_s5r (s5r));
+ s5r->state = SOCKS5_SOCKET_DOWNLOAD_DONE;
+ run_mhd_now (s5r->hd);
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Download curl failed: %s\n",
+ curl_easy_strerror (msg->data.result));
+ /* FIXME: indicate error somehow? close MHD connection badly as well? */
+ s5r->state = SOCKS5_SOCKET_DOWNLOAD_DONE;
+ run_mhd_now (s5r->hd);
+ break;
+ }
+ if (NULL == s5r->response)
+ s5r->response = curl_failure_response;
+ break;
+ case CURLMSG_LAST:
+ /* documentation says this is not used */
+ GNUNET_break (0);
+ break;
+ default:
+ /* unexpected status code */
+ GNUNET_break (0);
+ break;
}
};
} while (mret == CURLM_CALL_MULTI_PERFORM);
if (CURLM_OK != mret)
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "%s failed at %s:%d: `%s'\n",
+ "%s failed at %s:%d: `%s'\n",
"curl_multi_perform", __FILE__, __LINE__,
curl_multi_strerror (mret));
if (0 == running)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Suspending cURL multi loop, no more events pending\n");
+ "Suspending cURL multi loop, no more events pending\n");
return; /* nothing more in progress */
}
curl_download_prepare ();
if ( (0 == strcasecmp (MHD_HTTP_HEADER_HOST, key)) &&
(NULL != s5r->leho) )
value = s5r->leho;
- if (0 == strcasecmp (MHD_HTTP_HEADER_CONNECTION, key))
- value = "Close";
+ if (0 == strcasecmp (MHD_HTTP_HEADER_CONTENT_LENGTH, key))
+ return MHD_YES;
+ if (0 == strcasecmp (MHD_HTTP_HEADER_ACCEPT_ENCODING, key))
+ return MHD_YES;
GNUNET_asprintf (&hdr,
- "%s: %s",
- key,
- value);
+ "%s: %s",
+ key,
+ value);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Adding HEADER `%s' to HTTP request\n",
- hdr);
+ "Adding HEADER `%s' to HTTP request\n",
+ hdr);
s5r->headers = curl_slist_append (s5r->headers,
- hdr);
+ hdr);
GNUNET_free (hdr);
return MHD_YES;
}
{
struct Socks5Request *s5r = *con_cls;
char *curlurl;
+ char *curl_hosts;
char ipstring[INET6_ADDRSTRLEN];
char ipaddr[INET6_ADDRSTRLEN + 2];
const struct sockaddr *sa;
GNUNET_break (0);
return MHD_NO;
}
- if ( (NULL == s5r->curl) &&
- (SOCKS5_SOCKET_WITH_MHD == s5r->state) )
+ //Fresh connection.
+ if (SOCKS5_SOCKET_WITH_MHD == s5r->state)
{
/* first time here, initialize curl handle */
sa = (const struct sockaddr *) &s5r->destination_address;
switch (sa->sa_family)
{
- case AF_INET:
- s4 = (const struct sockaddr_in *) &s5r->destination_address;
- if (NULL == inet_ntop (AF_INET,
- &s4->sin_addr,
- ipstring,
- sizeof (ipstring)))
- {
- GNUNET_break (0);
- return MHD_NO;
- }
- GNUNET_snprintf (ipaddr,
- sizeof (ipaddr),
- "%s",
- ipstring);
- port = ntohs (s4->sin_port);
- break;
- case AF_INET6:
- s6 = (const struct sockaddr_in6 *) &s5r->destination_address;
- if (NULL == inet_ntop (AF_INET6,
- &s6->sin6_addr,
- ipstring,
- sizeof (ipstring)))
- {
- GNUNET_break (0);
- return MHD_NO;
- }
- GNUNET_snprintf (ipaddr,
- sizeof (ipaddr),
- "[%s]",
- ipstring);
- port = ntohs (s6->sin6_port);
- break;
- default:
- GNUNET_break (0);
- return MHD_NO;
+ case AF_INET:
+ s4 = (const struct sockaddr_in *) &s5r->destination_address;
+ if (NULL == inet_ntop (AF_INET,
+ &s4->sin_addr,
+ ipstring,
+ sizeof (ipstring)))
+ {
+ GNUNET_break (0);
+ return MHD_NO;
+ }
+ GNUNET_snprintf (ipaddr,
+ sizeof (ipaddr),
+ "%s",
+ ipstring);
+ port = ntohs (s4->sin_port);
+ break;
+ case AF_INET6:
+ s6 = (const struct sockaddr_in6 *) &s5r->destination_address;
+ if (NULL == inet_ntop (AF_INET6,
+ &s6->sin6_addr,
+ ipstring,
+ sizeof (ipstring)))
+ {
+ GNUNET_break (0);
+ return MHD_NO;
+ }
+ GNUNET_snprintf (ipaddr,
+ sizeof (ipaddr),
+ "%s",
+ ipstring);
+ port = ntohs (s6->sin6_port);
+ break;
+ default:
+ GNUNET_break (0);
+ return MHD_NO;
}
- s5r->curl = curl_easy_init ();
+ if (NULL == s5r->curl)
+ s5r->curl = curl_easy_init ();
if (NULL == s5r->curl)
return MHD_queue_response (con,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- curl_failure_response);
+ 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_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,
- port,
- s5r->url);
+ (HTTPS_PORT != s5r->port)
+ ? "http://%s:%d%s"
+ : "https://%s:%d%s",
+ (NULL != s5r->leho)
+ ? s5r->leho
+ : ipaddr,
+ port,
+ s5r->url);
curl_easy_setopt (s5r->curl,
- CURLOPT_URL,
- curlurl);
+ CURLOPT_URL,
+ curlurl);
GNUNET_free (curlurl);
-
if (0 == strcasecmp (meth, MHD_HTTP_METHOD_PUT))
{
s5r->state = SOCKS5_SOCKET_UPLOAD_STARTED;
else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_POST))
{
s5r->state = SOCKS5_SOCKET_UPLOAD_STARTED;
- curl_easy_setopt (s5r->curl, CURLOPT_POST, 1);
- curl_easy_setopt (s5r->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb);
+ 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);
s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED;
curl_easy_setopt (s5r->curl, CURLOPT_NOBODY, 1);
}
+ else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_OPTIONS))
+ {
+ s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED;
+ curl_easy_setopt (s5r->curl, CURLOPT_CUSTOMREQUEST, "OPTIONS");
+ }
else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_GET))
{
s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED;
else
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Unsupported HTTP method `%s'\n"),
- meth);
+ _("Unsupported HTTP method `%s'\n"),
+ meth);
curl_easy_cleanup (s5r->curl);
s5r->curl = NULL;
return MHD_NO;
if (HTTPS_PORT == s5r->port)
{
curl_easy_setopt (s5r->curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
- curl_easy_setopt (s5r->curl, CURLOPT_SSL_VERIFYPEER, 1L);
+ if (NULL != s5r->dane_data)
+ curl_easy_setopt (s5r->curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ else
+ 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 */
+ as only we have the domain name or the LEHO or the DANE record */
curl_easy_setopt (s5r->curl, CURLOPT_SSL_VERIFYHOST, 0L);
}
else
return MHD_NO;
}
MHD_get_connection_values (con,
- MHD_HEADER_KIND,
- &con_val_iter, s5r);
+ MHD_HEADER_KIND,
+ &con_val_iter, s5r);
curl_easy_setopt (s5r->curl, CURLOPT_HTTPHEADER, s5r->headers);
curl_download_prepare ();
return MHD_YES;
/* continuing to process request */
if (0 != *upload_data_size)
{
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Processing %u bytes UPLOAD\n",
+ (unsigned int) *upload_data_size);
+
+ /* 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);
+
left = GNUNET_MIN (*upload_data_size,
- sizeof (s5r->io_buf) - s5r->io_len);
- memcpy (&s5r->io_buf[s5r->io_len],
- upload_data,
- left);
+ sizeof (s5r->io_buf) - s5r->io_len);
+ GNUNET_memcpy (&s5r->io_buf[s5r->io_len],
+ upload_data,
+ left);
s5r->io_len += left;
*upload_data_size -= left;
GNUNET_assert (NULL != s5r->curl);
curl_easy_pause (s5r->curl, CURLPAUSE_CONT);
- curl_download_prepare ();
return MHD_YES;
}
if (SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Finished processing UPLOAD\n");
+ "Finished processing UPLOAD\n");
s5r->state = SOCKS5_SOCKET_UPLOAD_DONE;
}
if (NULL == s5r->response)
- return MHD_YES; /* too early to queue response, did not yet get headers from cURL */
+ return MHD_YES;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Queueing response with MHD\n");
+ "Queueing response with MHD\n");
+ run_mhd_now (s5r->hd);
return MHD_queue_response (con,
- s5r->response_code,
- s5r->response);
+ s5r->response_code,
+ s5r->response);
}
/**
- * Function called when MHD decides that we are done with a connection.
+ * Function called when MHD decides that we are done with a request.
*
* @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
mhd_completed_cb (void *cls,
- struct MHD_Connection *connection,
- void **con_cls,
- enum MHD_RequestTerminationCode toe)
+ struct MHD_Connection *connection,
+ void **con_cls,
+ enum MHD_RequestTerminationCode toe)
{
struct Socks5Request *s5r = *con_cls;
+ struct HttpResponseHeader *header;
if (NULL == s5r)
return;
if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe)
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "MHD encountered error handling request: %d\n",
- toe);
- cleanup_s5r (s5r);
+ "MHD encountered error handling request: %d\n",
+ toe);
+ if (NULL != s5r->curl)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Resetting cURL handle\n");
+ curl_multi_remove_handle (curl_multi, s5r->curl);
+ curl_slist_free_all (s5r->headers);
+ s5r->headers = NULL;
+ curl_easy_reset (s5r->curl);
+ s5r->rbuf_len = 0;
+ s5r->wbuf_len = 0;
+ s5r->io_len = 0;
+ }
+ if ( (NULL != s5r->response) &&
+ (curl_failure_response != s5r->response) )
+ MHD_destroy_response (s5r->response);
+ for (header = s5r->header_head; header != NULL; header = s5r->header_head)
+ {
+ GNUNET_CONTAINER_DLL_remove (s5r->header_head,
+ s5r->header_tail,
+ header);
+ GNUNET_free (header->type);
+ GNUNET_free (header->value);
+ GNUNET_free (header);
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished request for %s\n", s5r->url);
+ GNUNET_free (s5r->url);
+ s5r->state = SOCKS5_SOCKET_WITH_MHD;
+ s5r->url = NULL;
+ s5r->response = NULL;
*con_cls = NULL;
}
+/**
+ * Function called when MHD connection is opened or closed.
+ *
+ * @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 *`
+ * @param toe connection notification type
+ */
+static void
+mhd_connection_cb (void *cls,
+ struct MHD_Connection *connection,
+ void **con_cls,
+ enum MHD_ConnectionNotificationCode cnc)
+{
+ struct Socks5Request *s5r;
+ const union MHD_ConnectionInfo *ci;
+ int sock;
+
+ switch (cnc)
+ {
+ case MHD_CONNECTION_NOTIFY_STARTED:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection started...\n");
+ ci = MHD_get_connection_info (connection,
+ MHD_CONNECTION_INFO_CONNECTION_FD);
+ if (NULL == ci)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ sock = ci->connect_fd;
+ for (s5r = s5r_head; NULL != s5r; s5r = s5r->next)
+ {
+ if (GNUNET_NETWORK_get_fd (s5r->sock) == sock)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Context set...\n");
+ s5r->ssl_checked = GNUNET_NO;
+ *con_cls = s5r;
+ break;
+ }
+ }
+ break;
+ case MHD_CONNECTION_NOTIFY_CLOSED:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection closed... cleaning up\n");
+ s5r = *con_cls;
+ if (NULL == s5r)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Connection stale!\n");
+ return;
+ }
+ cleanup_s5r (s5r);
+ curl_download_prepare ();
+ *con_cls = NULL;
+ break;
+ default:
+ GNUNET_break (0);
+ }
+}
+
/**
* Function called when MHD first processes an incoming connection.
* Gives us the respective URI information.
*/
static void *
mhd_log_callback (void *cls,
- const char *url,
- struct MHD_Connection *connection)
+ const char *url,
+ struct MHD_Connection *connection)
{
struct Socks5Request *s5r;
const union MHD_ConnectionInfo *ci;
- int sock;
ci = MHD_get_connection_info (connection,
- MHD_CONNECTION_INFO_CONNECTION_FD);
+ MHD_CONNECTION_INFO_SOCKET_CONTEXT);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing %s\n", url);
if (NULL == ci)
{
GNUNET_break (0);
return NULL;
}
- sock = ci->connect_fd;
- for (s5r = s5r_head; NULL != s5r; s5r = s5r->next)
+ s5r = ci->socket_context;
+ if (NULL != s5r->url)
{
- if (GNUNET_NETWORK_get_fd (s5r->sock) == sock)
- {
- if (NULL != s5r->url)
- {
- GNUNET_break (0);
- return NULL;
- }
- s5r->url = GNUNET_strdup (url);
- GNUNET_SCHEDULER_cancel (s5r->timeout_task);
- s5r->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- return s5r;
- }
+ GNUNET_break (0);
+ return NULL;
}
- GNUNET_break (0);
- return NULL;
+ s5r->url = GNUNET_strdup (url);
+ if (NULL != s5r->timeout_task)
+ GNUNET_SCHEDULER_cancel (s5r->timeout_task);
+ s5r->timeout_task = NULL;
+ GNUNET_assert (s5r->state == SOCKS5_SOCKET_WITH_MHD);
+ return s5r;
}
kill_httpd (struct MhdHttpList *hd)
{
GNUNET_CONTAINER_DLL_remove (mhd_httpd_head,
- mhd_httpd_tail,
- hd);
+ mhd_httpd_tail,
+ 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)
* 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);
}
* 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);
/**
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) &&
{
/* daemon is idle, kill after timeout */
hd->httpd_task = GNUNET_SCHEDULER_add_delayed (MHD_CACHE_TIMEOUT,
- &kill_httpd_task,
- hd);
+ &kill_httpd_task,
+ hd);
}
else
{
hd->httpd_task =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- tv, wrs, wws,
- &do_httpd, hd);
+ tv, wrs, wws,
+ &do_httpd, hd);
}
if (NULL != wrs)
GNUNET_NETWORK_fdset_destroy (wrs);
* 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);
}
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,
- hd);
+ hd);
}
*/
static void*
load_file (const char* filename,
- unsigned int* size)
+ unsigned int* size)
{
void *buffer;
uint64_t fsize;
if (GNUNET_OK !=
GNUNET_DISK_file_size (filename, &fsize,
- GNUNET_YES, GNUNET_YES))
+ GNUNET_YES, GNUNET_YES))
return NULL;
if (fsize > MAX_PEM_SIZE)
return NULL;
*/
static int
load_key_from_file (gnutls_x509_privkey_t key,
- const char* keyfile)
+ const char* keyfile)
{
gnutls_datum_t key_data;
int ret;
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_("Unable to import private key from file `%s'\n"),
- keyfile);
+ keyfile);
}
GNUNET_free_non_null (key_data.data);
return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK;
*/
static int
load_cert_from_file (gnutls_x509_crt_t crt,
- const char* certfile)
+ const char* certfile)
{
gnutls_datum_t cert_data;
int ret;
if (GNUTLS_E_SUCCESS != ret)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to import certificate %s\n"), certfile);
+ _("Unable to import certificate %s\n"), certfile);
}
GNUNET_free_non_null (cert_data.data);
return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK;
struct ProxyGNSCertificate *pgc;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Generating TLS/SSL certificate for `%s'\n",
- name);
+ "Generating TLS/SSL certificate for `%s'\n",
+ 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);
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));
+ &serial,
+ sizeof (serial));
etime = time (NULL);
tm_data = localtime (&etime);
gnutls_x509_crt_set_activation_time (request,
- etime);
+ etime);
tm_data->tm_year++;
etime = mktime (tm_data);
gnutls_x509_crt_set_expiration_time (request,
- etime);
+ etime);
gnutls_x509_crt_sign (request,
- proxy_ca.cert,
- proxy_ca.key);
+ proxy_ca.cert,
+ proxy_ca.key);
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);
+ pgc->key, &key_buf_size);
gnutls_x509_crt_deinit (request);
return pgc;
}
}
for (hd = mhd_httpd_head; NULL != hd; hd = hd->next)
if ( (NULL != hd->domain) &&
- (0 == strcmp (hd->domain, domain)) )
+ (0 == strcmp (hd->domain, domain)) )
return hd;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Starting fresh MHD HTTPS instance for domain `%s'\n",
- domain);
+ "Starting fresh MHD HTTPS instance for domain `%s'\n",
+ domain);
pgc = generate_gns_certificate (domain);
hd = GNUNET_new (struct MhdHttpList);
hd->is_ssl = GNUNET_YES;
hd->domain = GNUNET_strdup (domain);
hd->proxy_cert = pgc;
hd->daemon = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SSL | MHD_USE_NO_LISTEN_SOCKET,
- 0,
- NULL, NULL,
- &create_response, hd,
- MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16,
- MHD_OPTION_NOTIFY_COMPLETED, &mhd_completed_cb, NULL,
- MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, NULL,
+ 0,
+ NULL, NULL,
+ &create_response, hd,
+ MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16,
+ MHD_OPTION_NOTIFY_COMPLETED, &mhd_completed_cb, NULL,
+ MHD_OPTION_NOTIFY_CONNECTION, &mhd_connection_cb, NULL,
+ MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, NULL,
MHD_OPTION_EXTERNAL_LOGGER, &mhd_error_log_callback, NULL,
- MHD_OPTION_HTTPS_MEM_KEY, pgc->key,
- MHD_OPTION_HTTPS_MEM_CERT, pgc->cert,
- MHD_OPTION_END);
+ MHD_OPTION_HTTPS_MEM_KEY, pgc->key,
+ MHD_OPTION_HTTPS_MEM_CERT, pgc->cert,
+ MHD_OPTION_END);
if (NULL == hd->daemon)
{
GNUNET_free (pgc);
return NULL;
}
GNUNET_CONTAINER_DLL_insert (mhd_httpd_head,
- mhd_httpd_tail,
- hd);
+ mhd_httpd_tail,
+ hd);
return hd;
}
* 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);
}
switch (s5r->port)
{
- case HTTPS_PORT:
- hd = lookup_ssl_httpd (s5r->domain);
- if (NULL == hd)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Failed to start HTTPS server for `%s'\n"),
- s5r->domain);
- cleanup_s5r (s5r);
- return;
- }
- break;
- case HTTP_PORT:
- default:
- GNUNET_assert (NULL != httpd);
- hd = httpd;
- break;
+ case HTTPS_PORT:
+ hd = lookup_ssl_httpd (s5r->domain);
+ if (NULL == hd)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Failed to start HTTPS server for `%s'\n"),
+ s5r->domain);
+ cleanup_s5r (s5r);
+ return;
+ }
+ break;
+ case HTTP_PORT:
+ default:
+ GNUNET_assert (NULL != httpd);
+ hd = httpd;
+ break;
}
fd = GNUNET_NETWORK_get_fd (s5r->sock);
addr = GNUNET_NETWORK_get_addr (s5r->sock);
if (MHD_YES != MHD_add_connection (hd->daemon, fd, addr, len))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Failed to pass client to MHD\n"));
+ _("Failed to pass client to MHD\n"));
cleanup_s5r (s5r);
return;
}
s5r->hd = hd;
schedule_httpd (hd);
s5r->timeout_task = GNUNET_SCHEDULER_add_delayed (HTTP_HANDSHAKE_TIMEOUT,
- &timeout_s5r_handshake,
- s5r);
+ &timeout_s5r_handshake,
+ 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);
+ s5r->wbuf,
+ s5r->wbuf_len);
if (len <= 0)
{
/* write error: connection closed, shutdown, etc.; just clean up */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Write Error\n");
cleanup_s5r (s5r);
return;
}
memmove (s5r->wbuf,
- &s5r->wbuf[len],
- s5r->wbuf_len - len);
+ &s5r->wbuf[len],
+ s5r->wbuf_len - len);
s5r->wbuf_len -= len;
if (s5r->wbuf_len > 0)
{
/* not done writing */
s5r->wtask =
GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
- s5r->sock,
- &do_write, s5r);
+ s5r->sock,
+ &do_write, s5r);
return;
}
switch (s5r->state)
{
- case SOCKS5_INIT:
- GNUNET_assert (0);
- break;
- case SOCKS5_REQUEST:
- GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s5r->rtask);
- break;
- case SOCKS5_DATA_TRANSFER:
- setup_data_transfer (s5r);
- return;
- case SOCKS5_WRITE_THEN_CLEANUP:
- cleanup_s5r (s5r);
- return;
- default:
- GNUNET_break (0);
- break;
+ case SOCKS5_INIT:
+ GNUNET_assert (0);
+ break;
+ case SOCKS5_REQUEST:
+ GNUNET_assert (NULL != s5r->rtask);
+ break;
+ case SOCKS5_DATA_TRANSFER:
+ setup_data_transfer (s5r);
+ return;
+ case SOCKS5_WRITE_THEN_CLEANUP:
+ cleanup_s5r (s5r);
+ return;
+ default:
+ GNUNET_break (0);
+ break;
}
}
*/
static void
signal_socks_failure (struct Socks5Request *s5r,
- enum Socks5StatusCode sc)
+ enum Socks5StatusCode sc)
{
struct Socks5ServerResponseMessage *s_resp;
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,
- &do_write, s5r);
+ s5r->sock,
+ &do_write, s5r);
}
s_resp->addr_type = SOCKS5_AT_IPV4;
/* zero out IPv4 address and port */
memset (&s_resp[1],
- 0,
- sizeof (struct in_addr) + sizeof (uint16_t));
+ 0,
+ 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,
- &do_write, s5r);
+ s5r->sock,
+ &do_write, 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
*/
static void
handle_gns_result (void *cls,
- uint32_t rd_count,
- const struct GNUNET_GNSRECORD_Data *rd)
+ uint32_t rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
{
struct Socks5Request *s5r = cls;
uint32_t i;
r = &rd[i];
switch (r->record_type)
{
- case GNUNET_DNSPARSER_TYPE_A:
- {
- struct sockaddr_in *in;
-
- if (sizeof (struct in_addr) != r->data_size)
- {
- GNUNET_break_op (0);
- break;
- }
- if (GNUNET_YES == got_ip)
- break;
- if (GNUNET_OK !=
- GNUNET_NETWORK_test_pf (PF_INET))
- break;
- got_ip = GNUNET_YES;
- in = (struct sockaddr_in *) &s5r->destination_address;
- in->sin_family = AF_INET;
- memcpy (&in->sin_addr,
- r->data,
- r->data_size);
- in->sin_port = htons (s5r->port);
+ case GNUNET_DNSPARSER_TYPE_A:
+ {
+ struct sockaddr_in *in;
+
+ if (sizeof (struct in_addr) != r->data_size)
+ {
+ GNUNET_break_op (0);
+ break;
+ }
+ if (GNUNET_YES == got_ip)
+ break;
+ if (GNUNET_OK !=
+ GNUNET_NETWORK_test_pf (PF_INET))
+ break;
+ got_ip = GNUNET_YES;
+ in = (struct sockaddr_in *) &s5r->destination_address;
+ in->sin_family = AF_INET;
+ GNUNET_memcpy (&in->sin_addr,
+ r->data,
+ r->data_size);
+ in->sin_port = htons (s5r->port);
#if HAVE_SOCKADDR_IN_SIN_LEN
- in->sin_len = sizeof (*in);
+ in->sin_len = sizeof (*in);
#endif
- }
- break;
- case GNUNET_DNSPARSER_TYPE_AAAA:
- {
- struct sockaddr_in6 *in;
-
- if (sizeof (struct in6_addr) != r->data_size)
- {
- GNUNET_break_op (0);
- break;
- }
- if (GNUNET_YES == got_ip)
- break;
- if (GNUNET_OK !=
- GNUNET_NETWORK_test_pf (PF_INET))
- break;
- /* FIXME: allow user to disable IPv6 per configuration option... */
- got_ip = GNUNET_YES;
- in = (struct sockaddr_in6 *) &s5r->destination_address;
- in->sin6_family = AF_INET6;
- memcpy (&in->sin6_addr,
- r->data,
- r->data_size);
- in->sin6_port = htons (s5r->port);
+ }
+ break;
+ case GNUNET_DNSPARSER_TYPE_AAAA:
+ {
+ struct sockaddr_in6 *in;
+
+ if (sizeof (struct in6_addr) != r->data_size)
+ {
+ GNUNET_break_op (0);
+ break;
+ }
+ if (GNUNET_YES == got_ip)
+ break;
+ if (GNUNET_OK !=
+ GNUNET_NETWORK_test_pf (PF_INET))
+ break;
+ /* FIXME: allow user to disable IPv6 per configuration option... */
+ got_ip = GNUNET_YES;
+ in = (struct sockaddr_in6 *) &s5r->destination_address;
+ in->sin6_family = AF_INET6;
+ GNUNET_memcpy (&in->sin6_addr,
+ r->data,
+ r->data_size);
+ in->sin6_port = htons (s5r->port);
#if HAVE_SOCKADDR_IN_SIN_LEN
- in->sin6_len = sizeof (*in);
+ in->sin6_len = sizeof (*in);
#endif
- }
- break;
- case GNUNET_GNSRECORD_TYPE_VPN:
- GNUNET_break (0); /* should have been translated within GNS */
- break;
- case GNUNET_GNSRECORD_TYPE_LEHO:
- GNUNET_free_non_null (s5r->leho);
- 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;
- default:
- /* don't care */
- break;
+ }
+ break;
+ case GNUNET_GNSRECORD_TYPE_VPN:
+ GNUNET_break (0); /* should have been translated within GNS */
+ break;
+ case GNUNET_GNSRECORD_TYPE_LEHO:
+ GNUNET_free_non_null (s5r->leho);
+ s5r->leho = GNUNET_strndup (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);
+ GNUNET_memcpy (s5r->dane_data,
+ &box[1],
+ s5r->dane_data_len);
+ break;
+ }
+ default:
+ /* don't care */
+ break;
}
}
if (GNUNET_YES != got_ip)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Name resolution failed to yield useful IP address.\n");
+ "Name resolution failed to yield useful IP address.\n");
signal_socks_failure (s5r,
- SOCKS5_STATUS_GENERAL_FAILURE);
+ SOCKS5_STATUS_GENERAL_FAILURE);
return;
}
s5r->state = SOCKS5_DATA_TRANSFER;
*/
static void
clear_from_s5r_rbuf (struct Socks5Request *s5r,
- size_t len)
+ size_t len)
{
GNUNET_assert (len <= s5r->rbuf_len);
memmove (s5r->rbuf,
- &s5r->rbuf[len],
- s5r->rbuf_len - len);
+ &s5r->rbuf[len],
+ s5r->rbuf_len - len);
s5r->rbuf_len -= len;
}
* 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;
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)) )
{
rlen = GNUNET_NETWORK_socket_recv (s5r->sock,
- &s5r->rbuf[s5r->rbuf_len],
- sizeof (s5r->rbuf) - s5r->rbuf_len);
+ &s5r->rbuf[s5r->rbuf_len],
+ sizeof (s5r->rbuf) - s5r->rbuf_len);
if (rlen <= 0)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "socks5 client disconnected.\n");
+ "socks5 client disconnected.\n");
cleanup_s5r (s5r);
return;
}
s5r->rbuf_len += rlen;
}
s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- s5r->sock,
- &do_s5r_read, s5r);
+ s5r->sock,
+ &do_s5r_read, s5r);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Processing %u bytes of socks data in state %d\n",
- s5r->rbuf_len,
- s5r->state);
+ "Processing %zu bytes of socks data in state %d\n",
+ s5r->rbuf_len,
+ s5r->state);
switch (s5r->state)
{
- case SOCKS5_INIT:
- c_hello = (const struct Socks5ClientHelloMessage*) &s5r->rbuf;
- if ( (s5r->rbuf_len < sizeof (struct Socks5ClientHelloMessage)) ||
- (s5r->rbuf_len < sizeof (struct Socks5ClientHelloMessage) + c_hello->num_auth_methods) )
- return; /* need more data */
- if (SOCKS_VERSION_5 != c_hello->version)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Unsupported socks version %d\n"),
- (int) c_hello->version);
- cleanup_s5r (s5r);
- return;
- }
- clear_from_s5r_rbuf (s5r,
- sizeof (struct Socks5ClientHelloMessage) + c_hello->num_auth_methods);
- GNUNET_assert (0 == s5r->wbuf_len);
- s_hello = (struct Socks5ServerHelloMessage *) &s5r->wbuf;
- 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);
- s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
- s5r->sock,
- &do_write, s5r);
- s5r->state = SOCKS5_REQUEST;
- return;
- case SOCKS5_REQUEST:
- c_req = (const struct Socks5ClientRequestMessage *) &s5r->rbuf;
- if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage))
- return;
- switch (c_req->command)
- {
- case SOCKS5_CMD_TCP_STREAM:
- /* handled below */
- break;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Unsupported socks command %d\n"),
- (int) c_req->command);
- signal_socks_failure (s5r,
- SOCKS5_STATUS_COMMAND_NOT_SUPPORTED);
+ case SOCKS5_INIT:
+ c_hello = (const struct Socks5ClientHelloMessage*) &s5r->rbuf;
+ if ( (s5r->rbuf_len < sizeof (struct Socks5ClientHelloMessage)) ||
+ (s5r->rbuf_len < sizeof (struct Socks5ClientHelloMessage) + c_hello->num_auth_methods) )
+ return; /* need more data */
+ if (SOCKS_VERSION_5 != c_hello->version)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Unsupported socks version %d\n"),
+ (int) c_hello->version);
+ cleanup_s5r (s5r);
+ return;
+ }
+ clear_from_s5r_rbuf (s5r,
+ sizeof (struct Socks5ClientHelloMessage) + c_hello->num_auth_methods);
+ GNUNET_assert (0 == s5r->wbuf_len);
+ s_hello = (struct Socks5ServerHelloMessage *) &s5r->wbuf;
+ s5r->wbuf_len = sizeof (struct Socks5ServerHelloMessage);
+ s_hello->version = SOCKS_VERSION_5;
+ s_hello->auth_method = SOCKS_AUTH_NONE;
+ GNUNET_assert (NULL == s5r->wtask);
+ s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+ s5r->sock,
+ &do_write, s5r);
+ s5r->state = SOCKS5_REQUEST;
return;
- }
- switch (c_req->addr_type)
- {
- case SOCKS5_AT_IPV4:
+ case SOCKS5_REQUEST:
+ c_req = (const struct Socks5ClientRequestMessage *) &s5r->rbuf;
+ if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage))
+ return;
+ switch (c_req->command)
{
- const struct in_addr *v4 = (const struct in_addr *) &c_req[1];
- const uint16_t *port = (const uint16_t *) &v4[1];
- struct sockaddr_in *in;
-
- s5r->port = ntohs (*port);
- if (HTTPS_PORT == s5r->port)
- {
+ case SOCKS5_CMD_TCP_STREAM:
+ /* handled below */
+ break;
+ default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("SSL connection to plain IPv4 address requested\n"));
+ _("Unsupported socks command %d\n"),
+ (int) c_req->command);
signal_socks_failure (s5r,
- SOCKS5_STATUS_CONNECTION_NOT_ALLOWED_BY_RULE);
+ SOCKS5_STATUS_COMMAND_NOT_SUPPORTED);
return;
- }
- alen = sizeof (struct in_addr);
- if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) +
- alen + sizeof (uint16_t))
- return; /* need more data */
- in = (struct sockaddr_in *) &s5r->destination_address;
- in->sin_family = AF_INET;
- in->sin_addr = *v4;
- in->sin_port = *port;
-#if HAVE_SOCKADDR_IN_SIN_LEN
- in->sin_len = sizeof (*in);
-#endif
- s5r->state = SOCKS5_DATA_TRANSFER;
}
- break;
- case SOCKS5_AT_IPV6:
+ switch (c_req->addr_type)
{
- const struct in6_addr *v6 = (const struct in6_addr *) &c_req[1];
- const uint16_t *port = (const uint16_t *) &v6[1];
- struct sockaddr_in6 *in;
-
- s5r->port = ntohs (*port);
- if (HTTPS_PORT == s5r->port)
- {
+ case SOCKS5_AT_IPV4:
+ {
+ const struct in_addr *v4 = (const struct in_addr *) &c_req[1];
+ const uint16_t *port = (const uint16_t *) &v4[1];
+ 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))
+ return; /* need more data */
+ in = (struct sockaddr_in *) &s5r->destination_address;
+ in->sin_family = AF_INET;
+ in->sin_addr = *v4;
+ in->sin_port = *port;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ in->sin_len = sizeof (*in);
+#endif
+ s5r->state = SOCKS5_DATA_TRANSFER;
+ }
+ break;
+ case SOCKS5_AT_IPV6:
+ {
+ const struct in6_addr *v6 = (const struct in6_addr *) &c_req[1];
+ const uint16_t *port = (const uint16_t *) &v6[1];
+ 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))
+ return; /* need more data */
+ in = (struct sockaddr_in6 *) &s5r->destination_address;
+ in->sin6_family = AF_INET6;
+ in->sin6_addr = *v6;
+ in->sin6_port = *port;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ in->sin6_len = sizeof (*in);
+#endif
+ s5r->state = SOCKS5_DATA_TRANSFER;
+ }
+ break;
+ case SOCKS5_AT_DOMAINNAME:
+ {
+ const uint8_t *dom_len;
+ const char *dom_name;
+ const uint16_t *port;
+
+ dom_len = (const uint8_t *) &c_req[1];
+ alen = *dom_len + 1;
+ if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) +
+ alen + sizeof (uint16_t))
+ return; /* need more data */
+ dom_name = (const char *) &dom_len[1];
+ port = (const uint16_t*) &dom_name[*dom_len];
+ s5r->domain = GNUNET_strndup (dom_name, *dom_len);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Requested connection is to %s:%d\n",
+ s5r->domain,
+ ntohs (*port));
+ s5r->state = SOCKS5_RESOLVING;
+ s5r->port = ntohs (*port);
+ s5r->gns_lookup = GNUNET_GNS_lookup (gns_handle,
+ s5r->domain,
+ &local_gns_zone,
+ GNUNET_DNSPARSER_TYPE_A,
+ GNUNET_NO /* only cached */,
+ &handle_gns_result,
+ s5r);
+ break;
+ }
+ default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("SSL connection to plain IPv4 address requested\n"));
+ _("Unsupported socks address type %d\n"),
+ (int) c_req->addr_type);
signal_socks_failure (s5r,
- SOCKS5_STATUS_CONNECTION_NOT_ALLOWED_BY_RULE);
+ SOCKS5_STATUS_ADDRESS_TYPE_NOT_SUPPORTED);
return;
- }
- alen = sizeof (struct in6_addr);
- if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) +
- alen + sizeof (uint16_t))
- return; /* need more data */
- in = (struct sockaddr_in6 *) &s5r->destination_address;
- in->sin6_family = AF_INET6;
- in->sin6_addr = *v6;
- in->sin6_port = *port;
-#if HAVE_SOCKADDR_IN_SIN_LEN
- in->sin6_len = sizeof (*in);
-#endif
- s5r->state = SOCKS5_DATA_TRANSFER;
}
- break;
- case SOCKS5_AT_DOMAINNAME:
+ clear_from_s5r_rbuf (s5r,
+ sizeof (struct Socks5ClientRequestMessage) +
+ alen + sizeof (uint16_t));
+ if (0 != s5r->rbuf_len)
{
- const uint8_t *dom_len;
- const char *dom_name;
- const uint16_t *port;
-
- dom_len = (const uint8_t *) &c_req[1];
- alen = *dom_len + 1;
- if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) +
- alen + sizeof (uint16_t))
- return; /* need more data */
- dom_name = (const char *) &dom_len[1];
- port = (const uint16_t*) &dom_name[*dom_len];
- s5r->domain = GNUNET_strndup (dom_name, *dom_len);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Requested connection is to %s:%d\n",
- s5r->domain,
- ntohs (*port));
- s5r->state = SOCKS5_RESOLVING;
- s5r->port = ntohs (*port);
- s5r->gns_lookup = GNUNET_GNS_lookup (gns_handle,
- s5r->domain,
- &local_gns_zone,
- GNUNET_DNSPARSER_TYPE_A,
- GNUNET_NO /* only cached */,
- (GNUNET_YES == do_shorten) ? &local_shorten_zone : NULL,
- &handle_gns_result,
- s5r);
- break;
+ /* read more bytes than healthy, why did the client send more!? */
+ GNUNET_break_op (0);
+ signal_socks_failure (s5r,
+ SOCKS5_STATUS_GENERAL_FAILURE);
+ return;
}
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Unsupported socks address type %d\n"),
- (int) c_req->addr_type);
- signal_socks_failure (s5r,
- SOCKS5_STATUS_ADDRESS_TYPE_NOT_SUPPORTED);
+ if (SOCKS5_DATA_TRANSFER == s5r->state)
+ {
+ /* if we are not waiting for GNS resolution, signal success */
+ signal_socks_success (s5r);
+ }
+ /* We are done reading right now */
+ GNUNET_SCHEDULER_cancel (s5r->rtask);
+ s5r->rtask = NULL;
return;
- }
- clear_from_s5r_rbuf (s5r,
- sizeof (struct Socks5ClientRequestMessage) +
- alen + sizeof (uint16_t));
- if (0 != s5r->rbuf_len)
- {
- /* read more bytes than healthy, why did the client send more!? */
- GNUNET_break_op (0);
- signal_socks_failure (s5r,
- SOCKS5_STATUS_GENERAL_FAILURE);
+ case SOCKS5_RESOLVING:
+ GNUNET_assert (0);
+ return;
+ case SOCKS5_DATA_TRANSFER:
+ GNUNET_assert (0);
+ return;
+ default:
+ GNUNET_assert (0);
return;
- }
- if (SOCKS5_DATA_TRANSFER == s5r->state)
- {
- /* if we are not waiting for GNS resolution, signal success */
- signal_socks_success (s5r);
- }
- /* We are done reading right now */
- GNUNET_SCHEDULER_cancel (s5r->rtask);
- s5r->rtask = GNUNET_SCHEDULER_NO_TASK;
- return;
- case SOCKS5_RESOLVING:
- GNUNET_assert (0);
- return;
- case SOCKS5_DATA_TRANSFER:
- GNUNET_assert (0);
- return;
- default:
- GNUNET_assert (0);
- return;
}
}
* @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,
"Got an inbound connection, waiting for data\n");
s5r = GNUNET_new (struct Socks5Request);
GNUNET_CONTAINER_DLL_insert (s5r_head,
- s5r_tail,
- s5r);
+ s5r_tail,
+ s5r);
s5r->sock = s;
s5r->state = SOCKS5_INIT;
s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
* 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");
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);
return NULL;
if (GNUNET_OK !=
GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa4,
- sizeof (sa4)))
+ sizeof (sa4)))
{
eno = errno;
GNUNET_NETWORK_socket_close (ls);
return NULL;
if (GNUNET_OK !=
GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa6,
- sizeof (sa6)))
+ sizeof (sa6)))
{
eno = errno;
GNUNET_NETWORK_socket_close (ls);
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Proxy listens on port %u\n",
+ "Proxy listens on port %llu\n",
port);
/* start MHD daemon for HTTP */
hd = GNUNET_new (struct MhdHttpList);
hd->daemon = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_NO_LISTEN_SOCKET,
- 0,
- NULL, NULL,
- &create_response, hd,
- MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16,
- MHD_OPTION_NOTIFY_COMPLETED, &mhd_completed_cb, NULL,
- MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, NULL,
- MHD_OPTION_END);
+ 0,
+ NULL, NULL,
+ &create_response, hd,
+ MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16,
+ MHD_OPTION_NOTIFY_COMPLETED, &mhd_completed_cb, NULL,
+ MHD_OPTION_NOTIFY_CONNECTION, &mhd_connection_cb, NULL,
+ MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, NULL,
+ MHD_OPTION_END);
if (NULL == hd->daemon)
{
GNUNET_free (hd);
}
-/**
- * Method called to inform about the egos of the shorten zone of this peer.
- *
- * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get,
- * this function is only called ONCE, and 'NULL' being passed in
- * @a ego does indicate an error (i.e. name is taken or no default
- * value is known). If @a ego is non-NULL and if '*ctx'
- * is set in those callbacks, the value WILL be passed to a subsequent
- * call to the identity callback of #GNUNET_IDENTITY_connect (if
- * that one was not NULL).
- *
- * @param cls closure, NULL
- * @param ego ego handle
- * @param ctx context for application to store data for this ego
- * (during the lifetime of this process, initially NULL)
- * @param name name assigned by the user for this ego,
- * NULL if the user just deleted the ego and it
- * must thus no longer be used
- */
-static void
-identity_shorten_cb (void *cls,
- struct GNUNET_IDENTITY_Ego *ego,
- void **ctx,
- const char *name)
-{
- id_op = NULL;
- if (NULL == ego)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("No ego configured for `shorten-zone`\n"));
- }
- else
- {
- local_shorten_zone = *GNUNET_IDENTITY_ego_get_private_key (ego);
- do_shorten = GNUNET_YES;
- }
- run_cont ();
-}
-
-
/**
* Method called to inform about the egos of the master zone of this peer.
*
*/
static void
identity_master_cb (void *cls,
- struct GNUNET_IDENTITY_Ego *ego,
- void **ctx,
- const char *name)
+ struct GNUNET_IDENTITY_Ego *ego,
+ void **ctx,
+ const char *name)
{
id_op = NULL;
if (NULL == ego)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("No ego configured for `%s`\n"),
- "gns-proxy");
+ _("No ego configured for `%s`\n"),
+ "gns-proxy");
GNUNET_SCHEDULER_shutdown ();
return;
}
GNUNET_IDENTITY_ego_get_public_key (ego,
- &local_gns_zone);
- id_op = GNUNET_IDENTITY_get (identity,
- "gns-short",
- &identity_shorten_cb,
- NULL);
+ &local_gns_zone);
+ run_cont ();
}
* @param c configuration
*/
static void
-run (void *cls, char *const *args, const char *cfgfile,
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *c)
{
char* cafile_cfg = NULL;
if (NULL == cafile)
{
if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns-proxy",
- "PROXY_CACERT",
- &cafile_cfg))
+ "PROXY_CACERT",
+ &cafile_cfg))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "gns-proxy",
- "PROXY_CACERT");
+ "gns-proxy",
+ "PROXY_CACERT");
return;
}
cafile = cafile_cfg;
(GNUNET_OK != load_key_from_file (proxy_ca.key, cafile)) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Failed to load SSL/TLS key and certificate from `%s'\n"),
- cafile);
+ _("Failed to load SSL/TLS key and certificate from `%s'\n"),
+ cafile);
gnutls_x509_crt_deinit (proxy_ca.cert);
gnutls_x509_privkey_deinit (proxy_ca.key);
gnutls_global_deinit ();
return;
}
identity = GNUNET_IDENTITY_connect (cfg,
- NULL, NULL);
+ NULL, NULL);
id_op = GNUNET_IDENTITY_get (identity,
- "gns-proxy",
- &identity_master_cb,
- NULL);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
- &do_shutdown, NULL);
+ "gns-proxy",
+ &identity_master_cb,
+ NULL);
+ GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
}
int
main (int argc, char *const *argv)
{
- static const struct GNUNET_GETOPT_CommandLineOption options[] = {
- {'p', "port", NULL,
- gettext_noop ("listen on specified port (default: 7777)"), 1,
- &GNUNET_GETOPT_set_ulong, &port},
- {'a', "authority", NULL,
- gettext_noop ("pem file to use as CA"), 1,
- &GNUNET_GETOPT_set_string, &cafile_opt},
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+
+ GNUNET_GETOPT_option_ulong ('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_END
};
static const char* page =
"</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", NULL);
- curl_failure_response = MHD_create_response_from_buffer (strlen (page),
- (void*)page,
- MHD_RESPMEM_PERSISTENT);
+ GNUNET_log_setup ("gnunet-gns-proxy",
+ "WARNING",
+ NULL);
+ curl_failure_response
+ = MHD_create_response_from_buffer (strlen (page),
+ (void *) page,
+ MHD_RESPMEM_PERSISTENT);
ret =
- (GNUNET_OK ==
- GNUNET_PROGRAM_run (argc, argv, "gnunet-gns-proxy",
- _("GNUnet GNS proxy"),
- options,
- &run, NULL)) ? 0 : 1;
+ (GNUNET_OK ==
+ GNUNET_PROGRAM_run (argc, argv,
+ "gnunet-gns-proxy",
+ _("GNUnet GNS proxy"),
+ options,
+ &run, NULL)) ? 0 : 1;
MHD_destroy_response (curl_failure_response);
GNUNET_free_non_null ((char *) argv);
- GNUNET_CRYPTO_ecdsa_key_clear (&local_shorten_zone);
return ret;
}