GNUnet  0.10.x
Data Structures | Macros | Enumerations | Functions | Variables
gnunet-gns-proxy.c File Reference

HTTP(S) proxy that rewrites URIs and fakes certificats to make GNS work with legacy browsers. More...

#include "platform.h"
#include <microhttpd.h>
#include "gnunet_curl_lib.h"
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <gnutls/abstract.h>
#include <gnutls/crypto.h>
#include <regex.h>
#include "gnunet_util_lib.h"
#include "gnunet_gns_service.h"
#include "gnunet_identity_service.h"
#include "gns.h"
Include dependency graph for gnunet-gns-proxy.c:

Go to the source code of this file.

Data Structures

struct  Socks5ClientHelloMessage
 Client hello in Socks5 protocol. More...
 
struct  Socks5ServerHelloMessage
 Server hello in Socks5 protocol. More...
 
struct  Socks5ClientRequestMessage
 Client socks request in Socks5 protocol. More...
 
struct  Socks5ServerResponseMessage
 Server response to client requests in Socks5 protocol. More...
 
struct  ProxyCA
 A structure for CA cert/key. More...
 
struct  ProxyGNSCertificate
 Structure for GNS certificates. More...
 
struct  MhdHttpList
 A structure for all running Httpds. More...
 
struct  HttpResponseHeader
 A header list. More...
 
struct  Socks5Request
 A structure for socks requests. More...
 

Macros

#define GNUNET_GNS_PROXY_PORT   7777
 Default Socks5 listen port. More...
 
#define MAX_HTTP_URI_LENGTH   2048
 Maximum supported length for a URI. More...
 
#define MAX_DANES   32
 Maximum number of DANE records we support per domain name (and port and protocol). More...
 
#define IO_BUFFERSIZE   CURL_MAX_WRITE_SIZE
 Size of the buffer for the data upload / download. More...
 
#define SOCKS_BUFFERSIZE   (256 + 32)
 Size of the read/write buffers for Socks. More...
 
#define HTTP_PORT   80
 Port for plaintext HTTP. More...
 
#define HTTPS_PORT   443
 Port for HTTPS. More...
 
#define MAX_PEM_SIZE   (10 * 1024)
 Largest allowed size for a PEM certificate. More...
 
#define MHD_CACHE_TIMEOUT   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
 After how long do we clean up unused MHD TLS instances? More...
 
#define HTTP_HANDSHAKE_TIMEOUT   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
 After how long do we clean up Socks5 handles that failed to show any activity with their respective MHD instance? More...
 
#define LOG_CURL_EASY(level, fun, rc)
 Log curl error. More...
 
#define SOCKS_VERSION_5   0x05
 Which SOCKS version do we speak? More...
 
#define SOCKS_AUTH_NONE   0
 Flag to set for 'no authentication'. More...
 

Enumerations

enum  Socks5Commands { SOCKS5_CMD_TCP_STREAM = 1, SOCKS5_CMD_TCP_PORT = 2, SOCKS5_CMD_UDP_PORT = 3 }
 Commands in Socks5. More...
 
enum  Socks5AddressType { SOCKS5_AT_IPV4 = 1, SOCKS5_AT_DOMAINNAME = 3, SOCKS5_AT_IPV6 = 4 }
 Address types in Socks5. More...
 
enum  Socks5StatusCode {
  SOCKS5_STATUS_REQUEST_GRANTED = 0, SOCKS5_STATUS_GENERAL_FAILURE = 1, SOCKS5_STATUS_CONNECTION_NOT_ALLOWED_BY_RULE = 2, SOCKS5_STATUS_NETWORK_UNREACHABLE = 3,
  SOCKS5_STATUS_HOST_UNREACHABLE = 4, SOCKS5_STATUS_CONNECTION_REFUSED_BY_HOST = 5, SOCKS5_STATUS_TTL_EXPIRED = 6, SOCKS5_STATUS_COMMAND_NOT_SUPPORTED = 7,
  SOCKS5_STATUS_ADDRESS_TYPE_NOT_SUPPORTED = 8
}
 Status codes in Socks5 response. More...
 
enum  SocksPhase {
  SOCKS5_INIT, SOCKS5_REQUEST, SOCKS5_RESOLVING, SOCKS5_DATA_TRANSFER,
  SOCKS5_WRITE_THEN_CLEANUP, SOCKS5_SOCKET_WITH_MHD, SOCKS5_SOCKET_UPLOAD_STARTED, SOCKS5_SOCKET_UPLOAD_DONE,
  SOCKS5_SOCKET_DOWNLOAD_STARTED, SOCKS5_SOCKET_DOWNLOAD_DONE
}
 The socks phases. More...
 

Functions

static void run_mhd_now (struct MhdHttpList *hd)
 Run MHD now, we have extra data ready for the callback. More...
 
static void cleanup_s5r (struct Socks5Request *s5r)
 Clean up s5r handles. More...
 
static void curl_download_prepare ()
 Ask cURL for the select() sets and schedule cURL operations. More...
 
static ssize_t mhd_content_cb (void *cls, uint64_t pos, char *buf, size_t max)
 Callback for MHD response generation. More...
 
static int check_ssl_certificate (struct Socks5Request *s5r)
 Check that the website has presented us with a valid X.509 certificate. More...
 
static size_t curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls)
 We're getting an HTTP response header from cURL. More...
 
static int create_mhd_response_from_s5r (struct Socks5Request *s5r)
 Create an MHD response object in s5r matching the information we got from curl. More...
 
static size_t curl_download_cb (void *ptr, size_t size, size_t nmemb, void *ctx)
 Handle response payload data from cURL. More...
 
static size_t curl_upload_cb (void *buf, size_t size, size_t nmemb, void *cls)
 cURL callback for uploaded (PUT/POST) data. More...
 
static void curl_task_download (void *cls)
 Task that is run when we are ready to receive more data from curl. More...
 
static int con_val_iter (void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
 Read HTTP request header field from the request. More...
 
static int create_response (void *cls, struct MHD_Connection *con, const char *url, const char *meth, const char *ver, const char *upload_data, size_t *upload_data_size, void **con_cls)
 Main MHD callback for handling requests. More...
 
static void mhd_completed_cb (void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
 Function called when MHD decides that we are done with a request. More...
 
static void mhd_connection_cb (void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_ConnectionNotificationCode cnc)
 Function called when MHD connection is opened or closed. More...
 
static void * mhd_log_callback (void *cls, const char *url, struct MHD_Connection *connection)
 Function called when MHD first processes an incoming connection. More...
 
static void kill_httpd (struct MhdHttpList *hd)
 Kill the given MHD daemon. More...
 
static void kill_httpd_task (void *cls)
 Task run whenever HTTP server is idle for too long. More...
 
static void do_httpd (void *cls)
 Task run whenever HTTP server operations are pending. More...
 
static void schedule_httpd (struct MhdHttpList *hd)
 Schedule MHD. More...
 
static void * load_file (const char *filename, unsigned int *size)
 Read file in filename. More...
 
static int load_key_from_file (gnutls_x509_privkey_t key, const char *keyfile)
 Load PEM key from file. More...
 
static int load_cert_from_file (gnutls_x509_crt_t crt, const char *certfile)
 Load cert from file. More...
 
static struct ProxyGNSCertificategenerate_gns_certificate (const char *name)
 Generate new certificate for specific name. More...
 
static void mhd_error_log_callback (void *cls, const char *fm, va_list ap)
 Function called by MHD with errors, suppresses them all. More...
 
static struct MhdHttpListlookup_ssl_httpd (const char *domain)
 Lookup (or create) an TLS MHD instance for a particular domain. More...
 
static void timeout_s5r_handshake (void *cls)
 Task run when a Socks5Request somehow fails to be associated with an MHD connection (i.e. More...
 
static void setup_data_transfer (struct Socks5Request *s5r)
 We're done with the Socks5 protocol, now we need to pass the connection data through to the final destination, either direct (if the protocol might not be HTTP), or via MHD (if the port looks like it should be HTTP). More...
 
static void do_write (void *cls)
 Write data from buffer to socks5 client, then continue with state machine. More...
 
static void signal_socks_failure (struct Socks5Request *s5r, enum Socks5StatusCode sc)
 Return a server response message indicating a failure to the client. More...
 
static void signal_socks_success (struct Socks5Request *s5r)
 Return a server response message indicating success. More...
 
static void handle_gns_result (void *cls, int tld, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
 Process GNS results for target domain. More...
 
static void clear_from_s5r_rbuf (struct Socks5Request *s5r, size_t len)
 Remove the first len bytes from the beginning of the read buffer. More...
 
static void do_s5r_read (void *cls)
 Read data from incoming Socks5 connection. More...
 
static void do_accept (void *cls)
 Accept new incoming connections. More...
 
static void do_shutdown (void *cls)
 Task run on shutdown. More...
 
static struct GNUNET_NETWORK_Handlebind_v4 ()
 Create an IPv4 listen socket bound to our port. More...
 
static struct GNUNET_NETWORK_Handlebind_v6 ()
 Create an IPv6 listen socket bound to our port. More...
 
static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
 Main function that will be run. More...
 
int main (int argc, char *const *argv)
 The main function for gnunet-gns-proxy. More...
 

Variables

static in_addr_t address
 The address to bind to. More...
 
static struct in6_addr address6
 The IPv6 address to bind to. More...
 
static uint16_t port = 7777
 The port the proxy is running on (default 7777) More...
 
static char * cafile_opt
 The CA file (pem) to use for the proxy CA. More...
 
static struct GNUNET_NETWORK_Handlelsock4
 The listen socket of the proxy for IPv4. More...
 
static struct GNUNET_NETWORK_Handlelsock6
 The listen socket of the proxy for IPv6. More...
 
static struct GNUNET_SCHEDULER_Taskltask4
 The listen task ID for IPv4. More...
 
static struct GNUNET_SCHEDULER_Taskltask6
 The listen task ID for IPv6. More...
 
static struct GNUNET_SCHEDULER_Taskcurl_download_task
 The cURL download task (curl multi API). More...
 
static CURLM * curl_multi
 The cURL multi handle. More...
 
static struct GNUNET_GNS_Handlegns_handle
 Handle to the GNS service. More...
 
static int disable_v6
 Disable IPv6. More...
 
static struct MhdHttpListmhd_httpd_head
 DLL for http/https daemons. More...
 
static struct MhdHttpListmhd_httpd_tail
 DLL for http/https daemons. More...
 
static struct MhdHttpListhttpd
 Daemon for HTTP (we have one per X.509 certificate, and then one for all HTTP connections; this is the one for HTTP, not HTTPS). More...
 
static struct Socks5Requests5r_head
 DLL of active socks requests. More...
 
static struct Socks5Requests5r_tail
 DLL of active socks requests. More...
 
static struct ProxyCA proxy_ca
 The CA for X.509 certificate generation. More...
 
static struct MHD_Response * curl_failure_response
 Response we return on cURL failures. More...
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 Our configuration. More...
 

Detailed Description

HTTP(S) proxy that rewrites URIs and fakes certificats to make GNS work with legacy browsers.

Author
Martin Schanzenbach
Christian Grothoff

TODO:

Definition in file gnunet-gns-proxy.c.

Macro Definition Documentation

◆ GNUNET_GNS_PROXY_PORT

#define GNUNET_GNS_PROXY_PORT   7777

Default Socks5 listen port.

Definition at line 52 of file gnunet-gns-proxy.c.

◆ MAX_HTTP_URI_LENGTH

#define MAX_HTTP_URI_LENGTH   2048

Maximum supported length for a URI.

Should die.

Deprecated:

Definition at line 58 of file gnunet-gns-proxy.c.

◆ MAX_DANES

#define MAX_DANES   32

Maximum number of DANE records we support per domain name (and port and protocol).

Definition at line 64 of file gnunet-gns-proxy.c.

Referenced by handle_gns_result().

◆ IO_BUFFERSIZE

#define IO_BUFFERSIZE   CURL_MAX_WRITE_SIZE

Size of the buffer for the data upload / download.

Must be enough for curl, thus CURL_MAX_WRITE_SIZE is needed here (16k).

Definition at line 70 of file gnunet-gns-proxy.c.

Referenced by create_mhd_response_from_s5r().

◆ SOCKS_BUFFERSIZE

#define SOCKS_BUFFERSIZE   (256 + 32)

Size of the read/write buffers for Socks.

Uses 256 bytes for the hostname (at most), plus a few bytes overhead for the messages.

Definition at line 77 of file gnunet-gns-proxy.c.

◆ HTTP_PORT

#define HTTP_PORT   80

Port for plaintext HTTP.

Definition at line 82 of file gnunet-gns-proxy.c.

◆ HTTPS_PORT

#define HTTPS_PORT   443

Port for HTTPS.

Definition at line 87 of file gnunet-gns-proxy.c.

Referenced by do_s5r_read().

◆ MAX_PEM_SIZE

#define MAX_PEM_SIZE   (10 * 1024)

Largest allowed size for a PEM certificate.

Definition at line 92 of file gnunet-gns-proxy.c.

Referenced by load_file().

◆ MHD_CACHE_TIMEOUT

#define MHD_CACHE_TIMEOUT   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)

After how long do we clean up unused MHD TLS instances?

Definition at line 97 of file gnunet-gns-proxy.c.

Referenced by schedule_httpd().

◆ HTTP_HANDSHAKE_TIMEOUT

#define HTTP_HANDSHAKE_TIMEOUT   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)

After how long do we clean up Socks5 handles that failed to show any activity with their respective MHD instance?

Definition at line 103 of file gnunet-gns-proxy.c.

Referenced by setup_data_transfer().

◆ LOG_CURL_EASY

#define LOG_CURL_EASY (   level,
  fun,
  rc 
)
Value:
GNUNET_log (level, \
_("%s failed at %s:%d: `%s'\n"), \
fun, \
__FILE__, \
__LINE__, \
curl_easy_strerror (rc))
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
#define GNUNET_log(kind,...)

Log curl error.

Parameters
levellog level
funname of curl_easy-function that gave the error
rcreturn code from curl

Definition at line 113 of file gnunet-gns-proxy.c.

◆ SOCKS_VERSION_5

#define SOCKS_VERSION_5   0x05

Which SOCKS version do we speak?

Definition at line 127 of file gnunet-gns-proxy.c.

Referenced by do_s5r_read(), signal_socks_failure(), and signal_socks_success().

◆ SOCKS_AUTH_NONE

#define SOCKS_AUTH_NONE   0

Flag to set for 'no authentication'.

Definition at line 132 of file gnunet-gns-proxy.c.

Referenced by do_s5r_read().

Enumeration Type Documentation

◆ Socks5Commands

Commands in Socks5.

Enumerator
SOCKS5_CMD_TCP_STREAM 

Establish TCP/IP stream.

SOCKS5_CMD_TCP_PORT 

Establish TCP port binding.

SOCKS5_CMD_UDP_PORT 

Establish UDP port binding.

Definition at line 138 of file gnunet-gns-proxy.c.

139 {
144 
149 
154 };
Establish TCP/IP stream.
Establish TCP port binding.
Establish UDP port binding.

◆ Socks5AddressType

Address types in Socks5.

Enumerator
SOCKS5_AT_IPV4 

IPv4 address.

SOCKS5_AT_DOMAINNAME 

IPv4 address.

SOCKS5_AT_IPV6 

IPv6 address.

Definition at line 160 of file gnunet-gns-proxy.c.

161 {
165  SOCKS5_AT_IPV4 = 1,
166 
171 
175  SOCKS5_AT_IPV6 = 4
176 
177 };
IPv4 address.
IPv6 address.

◆ Socks5StatusCode

Status codes in Socks5 response.

Enumerator
SOCKS5_STATUS_REQUEST_GRANTED 
SOCKS5_STATUS_GENERAL_FAILURE 
SOCKS5_STATUS_CONNECTION_NOT_ALLOWED_BY_RULE 
SOCKS5_STATUS_NETWORK_UNREACHABLE 
SOCKS5_STATUS_HOST_UNREACHABLE 
SOCKS5_STATUS_CONNECTION_REFUSED_BY_HOST 
SOCKS5_STATUS_TTL_EXPIRED 
SOCKS5_STATUS_COMMAND_NOT_SUPPORTED 
SOCKS5_STATUS_ADDRESS_TYPE_NOT_SUPPORTED 

Definition at line 183 of file gnunet-gns-proxy.c.

◆ SocksPhase

enum SocksPhase

The socks phases.

Enumerator
SOCKS5_INIT 

We're waiting to get the client hello.

SOCKS5_REQUEST 

We're waiting to get the initial request.

SOCKS5_RESOLVING 

We are currently resolving the destination.

SOCKS5_DATA_TRANSFER 

We're in transfer mode.

SOCKS5_WRITE_THEN_CLEANUP 

Finish writing the write buffer, then clean up.

SOCKS5_SOCKET_WITH_MHD 

Socket has been passed to MHD, do not close it anymore.

SOCKS5_SOCKET_UPLOAD_STARTED 

We've started receiving upload data from MHD.

SOCKS5_SOCKET_UPLOAD_DONE 

We've finished receiving upload data from MHD.

SOCKS5_SOCKET_DOWNLOAD_STARTED 

We've finished uploading data via CURL and can now download.

SOCKS5_SOCKET_DOWNLOAD_DONE 

We've finished receiving download data from cURL.

Definition at line 389 of file gnunet-gns-proxy.c.

390 {
394  SOCKS5_INIT,
395 
400 
405 
410 
415 
420 
425 
430 
435 
440 };
Socket has been passed to MHD, do not close it anymore.
We&#39;re waiting to get the client hello.
We&#39;re waiting to get the initial request.
We&#39;ve started receiving upload data from MHD.
We&#39;ve finished receiving upload data from MHD.
Finish writing the write buffer, then clean up.
We&#39;ve finished uploading data via CURL and can now download.
We&#39;ve finished receiving download data from cURL.
We are currently resolving the destination.
We&#39;re in transfer mode.

Function Documentation

◆ run_mhd_now()

static void run_mhd_now ( struct MhdHttpList hd)
static

Run MHD now, we have extra data ready for the callback.

Parameters
hdthe daemon to run now.

Definition at line 2581 of file gnunet-gns-proxy.c.

References do_httpd(), GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_cancel(), and MhdHttpList::httpd_task.

Referenced by create_response(), curl_download_cb(), curl_task_download(), and curl_upload_cb().

2582 {
2583  if (NULL != hd->httpd_task)
2586  hd);
2587 }
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1273
static void do_httpd(void *cls)
Task run whenever HTTP server operations are pending.
struct GNUNET_SCHEDULER_Task * httpd_task
The task ID.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cleanup_s5r()

static void cleanup_s5r ( struct Socks5Request s5r)
static

Clean up s5r handles.

Parameters
s5rthe handle to destroy

Definition at line 781 of file gnunet-gns-proxy.c.

References Socks5Request::con, Socks5Request::curl, curl_download_prepare(), curl_failure_response, curl_multi, Socks5Request::dane_data, Socks5Request::domain, Socks5Request::gns_lookup, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_free_non_null, GNUNET_GNS_lookup_with_tld_cancel(), GNUNET_log, GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_free_memory_only_(), GNUNET_NO, GNUNET_SCHEDULER_cancel(), Socks5Request::headers, Socks5Request::hosts, Socks5Request::leho, Socks5Request::num_danes, Socks5Request::response, Socks5Request::rtask, Socks5Request::sock, state, Socks5Request::suspended, Socks5Request::timeout_task, Socks5Request::url, and Socks5Request::wtask.

Referenced by do_s5r_read(), do_shutdown(), do_write(), mhd_connection_cb(), setup_data_transfer(), and timeout_s5r_handshake().

782 {
784  "Cleaning up socks request\n");
785  if (NULL != s5r->curl)
786  {
788  "Cleaning up cURL handle\n");
789  curl_multi_remove_handle (curl_multi,
790  s5r->curl);
791  curl_easy_cleanup (s5r->curl);
792  s5r->curl = NULL;
793  }
794  if (s5r->suspended)
795  {
796  s5r->suspended = GNUNET_NO;
797  MHD_resume_connection (s5r->con);
798  }
799  curl_slist_free_all (s5r->headers);
800  if (NULL != s5r->hosts)
801  {
802  curl_slist_free_all (s5r->hosts);
803  }
804  if ( (NULL != s5r->response) &&
805  (curl_failure_response != s5r->response) )
806  {
807  MHD_destroy_response (s5r->response);
808  s5r->response = NULL;
809  }
810  if (NULL != s5r->rtask)
811  {
813  s5r->rtask = NULL;
814  }
815  if (NULL != s5r->timeout_task)
816  {
818  s5r->timeout_task = NULL;
819  }
820  if (NULL != s5r->wtask)
821  {
823  s5r->wtask = NULL;
824  }
825  if (NULL != s5r->gns_lookup)
826  {
828  s5r->gns_lookup = NULL;
829  }
830  if (NULL != s5r->sock)
831  {
832  if (SOCKS5_SOCKET_WITH_MHD <= s5r->state)
834  else
836  s5r->sock = NULL;
837  }
839  s5r_tail,
840  s5r);
842  GNUNET_free_non_null (s5r->leho);
843  GNUNET_free_non_null (s5r->url);
844  for (unsigned int i=0;i<s5r->num_danes;i++)
845  GNUNET_free (s5r->dane_data[i]);
846  GNUNET_free (s5r);
847 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static struct Socks5Request * s5r_tail
DLL of active socks requests.
void * GNUNET_GNS_lookup_with_tld_cancel(struct GNUNET_GNS_LookupWithTldRequest *ltr)
Cancel pending lookup request.
Definition: gns_tld_api.c:330
struct GNUNET_SCHEDULER_Task * wtask
Client socket write task.
struct MHD_Connection * con
MHD connection for this request.
char * dane_data[32+1]
Payload of the DANE records encountered.
static struct MHD_Response * curl_failure_response
Response we return on cURL failures.
struct GNUNET_NETWORK_Handle * sock
The client socket.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
void GNUNET_NETWORK_socket_free_memory_only_(struct GNUNET_NETWORK_Handle *desc)
Only free memory of a socket, keep the file descriptor untouched.
Definition: network.c:680
enum State state
current state of profiling
int suspended
Did we suspend MHD processing?
unsigned int num_danes
Number of entries used in dane_data_len and dane_data.
struct GNUNET_GNS_LookupWithTldRequest * gns_lookup
Handle to GNS lookup, during SOCKS5_RESOLVING phase.
struct curl_slist * headers
HTTP request headers for the curl request.
char * domain
the domain name to server (only important for TLS)
struct MHD_Response * response
MHD response object for this request.
struct GNUNET_SCHEDULER_Task * rtask
Client socket read task.
static struct Socks5Request * s5r_head
DLL of active socks requests.
struct GNUNET_SCHEDULER_Task * timeout_task
Timeout task.
struct curl_slist * hosts
DNS->IP mappings resolved through GNS.
char * leho
DNS Legacy Host Name as given by GNS, NULL if not given.
#define GNUNET_log(kind,...)
char * url
The URL to fetch.
static CURLM * curl_multi
The cURL multi handle.
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:604
#define GNUNET_free(ptr)
Wrapper around free.
CURL * curl
Handle to cURL.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
Here is the call graph for this function:
Here is the caller graph for this function:

◆ curl_download_prepare()

static void curl_download_prepare ( )
static

Ask cURL for the select() sets and schedule cURL operations.

Definition at line 1574 of file gnunet-gns-proxy.c.

References curl_multi, curl_task_download(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_NETWORK_fdset_copy_native(), GNUNET_NETWORK_fdset_create(), GNUNET_NETWORK_fdset_destroy(), GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_add_select(), GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_TIME_relative_multiply(), GNUNET_TIME_UNIT_FOREVER_REL, and GNUNET_TIME_UNIT_MILLISECONDS.

Referenced by cleanup_s5r(), create_response(), curl_task_download(), mhd_completed_cb(), mhd_connection_cb(), and mhd_content_cb().

1575 {
1576  CURLMcode mret;
1577  fd_set rs;
1578  fd_set ws;
1579  fd_set es;
1580  int max;
1581  struct GNUNET_NETWORK_FDSet *grs;
1582  struct GNUNET_NETWORK_FDSet *gws;
1583  long to;
1584  struct GNUNET_TIME_Relative rtime;
1585 
1587  "Scheduling CURL interaction\n");
1588  if (NULL != curl_download_task)
1589  {
1591  curl_download_task = NULL;
1592  }
1593  max = -1;
1594  FD_ZERO (&rs);
1595  FD_ZERO (&ws);
1596  FD_ZERO (&es);
1597  if (CURLM_OK != (mret = curl_multi_fdset (curl_multi,
1598  &rs,
1599  &ws,
1600  &es,
1601  &max)))
1602  {
1604  "%s failed at %s:%d: `%s'\n",
1605  "curl_multi_fdset", __FILE__, __LINE__,
1606  curl_multi_strerror (mret));
1607  return;
1608  }
1609  to = -1;
1610  GNUNET_break (CURLM_OK ==
1611  curl_multi_timeout (curl_multi,
1612  &to));
1613  if (-1 == to)
1615  else
1617  to);
1618  if (-1 != max)
1619  {
1620  grs = GNUNET_NETWORK_fdset_create ();
1621  gws = GNUNET_NETWORK_fdset_create ();
1623  &rs,
1624  max + 1);
1626  &ws,
1627  max + 1);
1629  rtime,
1630  grs,
1631  gws,
1633  curl_multi);
1636  }
1637  else
1638  {
1641  curl_multi);
1642  }
1643 }
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
void GNUNET_NETWORK_fdset_copy_native(struct GNUNET_NETWORK_FDSet *to, const fd_set *from, int nfds)
Copy a native fd set into the GNUnet representation.
Definition: network.c:1308
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1554
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1246
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1538
collection of IO descriptors
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition: scheduler.c:1829
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:439
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
static struct GNUNET_SCHEDULER_Task * curl_download_task
The cURL download task (curl multi API).
#define GNUNET_log(kind,...)
static void curl_task_download(void *cls)
Task that is run when we are ready to receive more data from curl.
Run with the default priority (normal P2P operations).
static CURLM * curl_multi
The cURL multi handle.
Time for relative time used by GNUnet, in microseconds.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mhd_content_cb()

static ssize_t mhd_content_cb ( void *  cls,
uint64_t  pos,
char *  buf,
size_t  max 
)
static

Callback for MHD response generation.

This function is called from MHD whenever MHD expects to get data back. Copies data from the io_buf, if available.

Parameters
clsclosure with our struct Socks5Request
posin buffer
bufwhere to copy data
maxavailable space in buf
Returns
number of bytes written to buf

Definition at line 868 of file gnunet-gns-proxy.c.

References Socks5Request::con, Socks5Request::curl, curl_download_prepare(), Socks5Request::curl_paused, Socks5Request::domain, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_MIN, GNUNET_NO, GNUNET_YES, Socks5Request::io_buf, Socks5Request::io_len, SOCKS5_SOCKET_DOWNLOAD_DONE, SOCKS5_SOCKET_UPLOAD_DONE, SOCKS5_SOCKET_UPLOAD_STARTED, Socks5Request::state, Socks5Request::suspended, and Socks5Request::url.

Referenced by create_mhd_response_from_s5r().

872 {
873  struct Socks5Request *s5r = cls;
874  size_t bytes_to_copy;
875 
876  if ( (SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state) ||
877  (SOCKS5_SOCKET_UPLOAD_DONE == s5r->state) )
878  {
879  /* we're still not done with the upload, do not yet
880  start the download, the IO buffer is still full
881  with upload data. */
883  "Pausing MHD download %s%s, not yet ready for download\n",
884  s5r->domain,
885  s5r->url);
886  return 0; /* not yet ready for data download */
887  }
888  bytes_to_copy = GNUNET_MIN (max,
889  s5r->io_len);
890  if ( (0 == bytes_to_copy) &&
892  {
894  "Pausing MHD download %s%s, no data available\n",
895  s5r->domain,
896  s5r->url);
897  if (NULL != s5r->curl)
898  {
900  "Continuing CURL interaction for %s%s\n",
901  s5r->domain,
902  s5r->url);
903  if (GNUNET_YES == s5r->curl_paused)
904  {
905  s5r->curl_paused = GNUNET_NO;
906  curl_easy_pause (s5r->curl,
907  CURLPAUSE_CONT);
908  }
910  }
911  if (GNUNET_NO == s5r->suspended)
912  {
913  MHD_suspend_connection (s5r->con);
914  s5r->suspended = GNUNET_YES;
915  }
916  return 0; /* more data later */
917  }
918  if ( (0 == bytes_to_copy) &&
920  {
922  "Completed MHD download %s%s\n",
923  s5r->domain,
924  s5r->url);
925  return MHD_CONTENT_READER_END_OF_STREAM;
926  }
928  "Writing %llu/%llu bytes to %s%s\n",
929  (unsigned long long) bytes_to_copy,
930  (unsigned long long) s5r->io_len,
931  s5r->domain,
932  s5r->url);
934  s5r->io_buf,
935  bytes_to_copy);
936  memmove (s5r->io_buf,
937  &s5r->io_buf[bytes_to_copy],
938  s5r->io_len - bytes_to_copy);
939  s5r->io_len -= bytes_to_copy;
940  if ( (NULL != s5r->curl) &&
941  (GNUNET_YES == s5r->curl_paused) )
942  {
944  "Continuing CURL interaction for %s%s\n",
945  s5r->domain,
946  s5r->url);
947  s5r->curl_paused = GNUNET_NO;
948  curl_easy_pause (s5r->curl,
949  CURLPAUSE_CONT);
950  }
951  return bytes_to_copy;
952 }
struct MHD_Connection * con
MHD connection for this request.
int curl_paused
Did we pause CURL processing?
#define GNUNET_NO
Definition: gnunet_common.h:81
We&#39;ve started receiving upload data from MHD.
We&#39;ve finished receiving upload data from MHD.
size_t io_len
Number of bytes already in the IO buffer.
#define GNUNET_memcpy(dst, src, n)
int suspended
Did we suspend MHD processing?
enum SocksPhase state
The socks state.
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:83
char * domain
the domain name to server (only important for TLS)
static char buf[2048]
static void curl_download_prepare()
Ask cURL for the select() sets and schedule cURL operations.
We&#39;ve finished receiving download data from cURL.
#define GNUNET_log(kind,...)
char io_buf[CURL_MAX_WRITE_SIZE]
Buffer we use for moving data between MHD and curl (in both directions).
#define GNUNET_YES
Definition: gnunet_common.h:80
char * url
The URL to fetch.
A structure for socks requests.
CURL * curl
Handle to cURL.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_ssl_certificate()

static int check_ssl_certificate ( struct Socks5Request s5r)
static

Check that the website has presented us with a valid X.509 certificate.

The certificate must either match the domain name or the LEHO name (or, if available, the TLSA record).

Parameters
s5rrequest to check for.
Returns
GNUNET_OK if the certificate is valid

Definition at line 964 of file gnunet-gns-proxy.c.

References _, Socks5Request::curl, Socks5Request::dane_data, Socks5Request::dane_data_len, Socks5Request::domain, GNUNET_break, GNUNET_DNSPARSER_MAX_NAME_LENGTH, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, Socks5Request::leho, name, Socks5Request::num_danes, size, Socks5Request::ssl_checked, and verify.

Referenced by curl_check_hdr().

965 {
966  unsigned int cert_list_size;
967  const gnutls_datum_t *chainp;
968  const struct curl_tlssessioninfo *tlsinfo;
969  char certdn[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 3];
970  size_t size;
971  gnutls_x509_crt_t x509_cert;
972  int rc;
973  const char *name;
974 
975  s5r->ssl_checked = GNUNET_YES;
977  "Checking X.509 certificate\n");
978  if (CURLE_OK !=
979  curl_easy_getinfo (s5r->curl,
980  CURLINFO_TLS_SESSION,
981  &tlsinfo))
982  return GNUNET_SYSERR;
983  if (CURLSSLBACKEND_GNUTLS != tlsinfo->backend)
984  {
986  _("Unsupported CURL TLS backend %d\n"),
987  tlsinfo->backend);
988  return GNUNET_SYSERR;
989  }
990  chainp = gnutls_certificate_get_peers (tlsinfo->internals,
991  &cert_list_size);
992  if ( (! chainp) ||
993  (0 == cert_list_size) )
994  return GNUNET_SYSERR;
995 
996  size = sizeof (certdn);
997  /* initialize an X.509 certificate structure. */
998  gnutls_x509_crt_init (&x509_cert);
999  gnutls_x509_crt_import (x509_cert,
1000  chainp,
1001  GNUTLS_X509_FMT_DER);
1002 
1003  if (0 != (rc = gnutls_x509_crt_get_dn_by_oid (x509_cert,
1004  GNUTLS_OID_X520_COMMON_NAME,
1005  0, /* the first and only one */
1006  0 /* no DER encoding */,
1007  certdn,
1008  &size)))
1009  {
1011  _("Failed to fetch CN from cert: %s\n"),
1012  gnutls_strerror(rc));
1013  gnutls_x509_crt_deinit (x509_cert);
1014  return GNUNET_SYSERR;
1015  }
1016  /* check for TLSA/DANE records */
1017 #if HAVE_GNUTLS_DANE
1018  if (0 != s5r->num_danes)
1019  {
1020  dane_state_t dane_state;
1021  dane_query_t dane_query;
1022  unsigned int verify;
1023 
1024  /* FIXME: add flags to gnutls to NOT read UNBOUND_ROOT_KEY_FILE here! */
1025  if (0 != (rc = dane_state_init (&dane_state,
1026 #ifdef DANE_F_IGNORE_DNSSEC
1027  DANE_F_IGNORE_DNSSEC |
1028 #endif
1029  DANE_F_IGNORE_LOCAL_RESOLVER)))
1030  {
1032  _("Failed to initialize DANE: %s\n"),
1033  dane_strerror(rc));
1034  gnutls_x509_crt_deinit (x509_cert);
1035  return GNUNET_SYSERR;
1036  }
1037  s5r->dane_data[s5r->num_danes] = NULL;
1038  s5r->dane_data_len[s5r->num_danes] = 0;
1039  if (0 != (rc = dane_raw_tlsa (dane_state,
1040  &dane_query,
1041  s5r->dane_data,
1042  s5r->dane_data_len,
1043  GNUNET_YES,
1044  GNUNET_NO)))
1045  {
1047  _("Failed to parse DANE record: %s\n"),
1048  dane_strerror(rc));
1049  dane_state_deinit (dane_state);
1050  gnutls_x509_crt_deinit (x509_cert);
1051  return GNUNET_SYSERR;
1052  }
1053  if (0 != (rc = dane_verify_crt_raw (dane_state,
1054  chainp,
1055  cert_list_size,
1056  gnutls_certificate_type_get (tlsinfo->internals),
1057  dane_query,
1058  0, 0,
1059  &verify)))
1060  {
1062  _("Failed to verify TLS connection using DANE: %s\n"),
1063  dane_strerror(rc));
1064  dane_query_deinit (dane_query);
1065  dane_state_deinit (dane_state);
1066  gnutls_x509_crt_deinit (x509_cert);
1067  return GNUNET_SYSERR;
1068  }
1069  if (0 != verify)
1070  {
1072  _("Failed DANE verification failed with GnuTLS verify status code: %u\n"),
1073  verify);
1074  dane_query_deinit (dane_query);
1075  dane_state_deinit (dane_state);
1076  gnutls_x509_crt_deinit (x509_cert);
1077  return GNUNET_SYSERR;
1078  }
1079  dane_query_deinit (dane_query);
1080  dane_state_deinit (dane_state);
1081  /* success! */
1082  }
1083  else
1084 #endif
1085  {
1086  /* try LEHO or ordinary domain name X509 verification */
1087  name = s5r->domain;
1088  if (NULL != s5r->leho)
1089  name = s5r->leho;
1090  if (NULL != name)
1091  {
1092  if (0 == (rc = gnutls_x509_crt_check_hostname (x509_cert,
1093  name)))
1094  {
1096  _("TLS certificate subject name (%s) does not match `%s': %d\n"),
1097  certdn,
1098  name,
1099  rc);
1100  gnutls_x509_crt_deinit (x509_cert);
1101  return GNUNET_SYSERR;
1102  }
1103  }
1104  else
1105  {
1106  /* we did not even have the domain name!? */
1107  GNUNET_break (0);
1108  return GNUNET_SYSERR;
1109  }
1110  }
1111  gnutls_x509_crt_deinit (x509_cert);
1112  return GNUNET_OK;
1113 }
char * dane_data[32+1]
Payload of the DANE records encountered.
int dane_data_len[32+1]
Number of bytes in dane_data.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
#define GNUNET_DNSPARSER_MAX_NAME_LENGTH
Maximum length of a name in DNS.
int ssl_checked
X.509 Certificate status.
static int verify
Verify mode.
unsigned int num_danes
Number of entries used in dane_data_len and dane_data.
char * domain
the domain name to server (only important for TLS)
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:67
const char * name
char * leho
DNS Legacy Host Name as given by GNS, NULL if not given.
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:80
CURL * curl
Handle to cURL.
Here is the caller graph for this function:

◆ curl_check_hdr()

static size_t curl_check_hdr ( void *  buffer,
size_t  size,
size_t  nmemb,
void *  cls 
)
static

We're getting an HTTP response header from cURL.

Convert it to the MHD response headers. Mostly copies the headers, but makes special adjustments to "Set-Cookie" and "Location" headers as those may need to be changed from the LEHO to the domain the browser expects.

Parameters
buffercurl buffer with a single line of header data; not 0-terminated!
sizecurl blocksize
nmembcurl blocknumber
clsour struct Socks5Request *
Returns
size of processed bytes

Definition at line 1129 of file gnunet-gns-proxy.c.

References _, check_ssl_certificate(), cleanup(), Socks5Request::domain, GNUNET_asprintf(), GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_free_non_null, GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_strdup, GNUNET_strndup, GNUNET_YES, Socks5Request::header_head, Socks5Request::header_tail, Socks5Request::is_tls, Socks5Request::leho, Socks5Request::ssl_checked, HttpResponseHeader::type, and HttpResponseHeader::value.

Referenced by create_response().

1133 {
1134  struct Socks5Request *s5r = cls;
1135  struct HttpResponseHeader *header;
1136  size_t bytes = size * nmemb;
1137  char *ndup;
1138  const char *hdr_type;
1139  const char *cookie_domain;
1140  char *hdr_val;
1141  char *new_cookie_hdr;
1142  char *new_location;
1143  size_t offset;
1144  size_t delta_cdomain;
1145  int domain_matched;
1146  char *tok;
1147 
1149  "Receiving HTTP response header from CURL\n");
1150  /* first, check TLS certificate */
1151  if ( (GNUNET_YES != s5r->ssl_checked) &&
1152  (GNUNET_YES == s5r->is_tls))
1153  //(HTTPS_PORT == s5r->port))
1154  {
1155  if (GNUNET_OK != check_ssl_certificate (s5r))
1156  return 0;
1157  }
1158  ndup = GNUNET_strndup (buffer,
1159  bytes);
1160  hdr_type = strtok (ndup,
1161  ":");
1162  if (NULL == hdr_type)
1163  {
1164  GNUNET_free (ndup);
1165  return bytes;
1166  }
1167  hdr_val = strtok (NULL,
1168  "");
1169  if (NULL == hdr_val)
1170  {
1171  GNUNET_free (ndup);
1172  return bytes;
1173  }
1174  if (' ' == *hdr_val)
1175  hdr_val++;
1176 
1177  /* custom logic for certain header types */
1178  new_cookie_hdr = NULL;
1179  if ( (NULL != s5r->leho) &&
1180  (0 == strcasecmp (hdr_type,
1181  MHD_HTTP_HEADER_SET_COOKIE)) )
1182 
1183  {
1184  new_cookie_hdr = GNUNET_malloc (strlen (hdr_val) +
1185  strlen (s5r->domain) + 1);
1186  offset = 0;
1187  domain_matched = GNUNET_NO; /* make sure we match domain at most once */
1188  for (tok = strtok (hdr_val, ";"); NULL != tok; tok = strtok (NULL, ";"))
1189  {
1190  if ( (0 == strncasecmp (tok,
1191  " domain",
1192  strlen (" domain"))) &&
1193  (GNUNET_NO == domain_matched) )
1194  {
1195  domain_matched = GNUNET_YES;
1196  cookie_domain = tok + strlen (" domain") + 1;
1197  if (strlen (cookie_domain) < strlen (s5r->leho))
1198  {
1199  delta_cdomain = strlen (s5r->leho) - strlen (cookie_domain);
1200  if (0 == strcasecmp (cookie_domain,
1201  s5r->leho + delta_cdomain))
1202  {
1203  offset += sprintf (new_cookie_hdr + offset,
1204  " domain=%s;",
1205  s5r->domain);
1206  continue;
1207  }
1208  }
1209  else if (0 == strcmp (cookie_domain,
1210  s5r->leho))
1211  {
1212  offset += sprintf (new_cookie_hdr + offset,
1213  " domain=%s;",
1214  s5r->domain);
1215  continue;
1216  }
1217  else if ( ('.' == cookie_domain[0]) &&
1218  (0 == strcmp (&cookie_domain[1],
1219  s5r->leho)) )
1220  {
1221  offset += sprintf (new_cookie_hdr + offset,
1222  " domain=.%s;",
1223  s5r->domain);
1224  continue;
1225  }
1227  _("Cookie domain `%s' supplied by server is invalid\n"),
1228  tok);
1229  }
1230  GNUNET_memcpy (new_cookie_hdr + offset,
1231  tok,
1232  strlen (tok));
1233  offset += strlen (tok);
1234  new_cookie_hdr[offset++] = ';';
1235  }
1236  hdr_val = new_cookie_hdr;
1237  }
1238 
1239  new_location = NULL;
1240  if (0 == strcasecmp (MHD_HTTP_HEADER_TRANSFER_ENCODING,
1241  hdr_type))
1242  {
1243  /* Ignore transfer encoding, set automatically by MHD if required */
1244  goto cleanup;
1245  }
1246  if ((0 == strcasecmp (MHD_HTTP_HEADER_LOCATION,
1247  hdr_type)))
1248  {
1249  char *leho_host;
1250 
1251  GNUNET_asprintf (&leho_host,
1252  (GNUNET_YES != s5r->is_tls) //(HTTPS_PORT != s5r->port)
1253  ? "http://%s"
1254  : "https://%s",
1255  s5r->leho);
1256  if (0 == strncmp (leho_host,
1257  hdr_val,
1258  strlen (leho_host)))
1259  {
1260  GNUNET_asprintf (&new_location,
1261  "%s%s%s",
1262  (GNUNET_YES != s5r->is_tls) //(HTTPS_PORT != s5r->port)
1263  ? "http://"
1264  : "https://",
1265  s5r->domain,
1266  hdr_val + strlen (leho_host));
1267  hdr_val = new_location;
1268  }
1269  GNUNET_free (leho_host);
1270  }
1271  if (0 == strcasecmp (MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
1272  hdr_type))
1273  {
1274  char *leho_host;
1275 
1276  GNUNET_asprintf (&leho_host,
1277  (GNUNET_YES != s5r->is_tls) //(HTTPS_PORT != s5r->port)
1278  ? "http://%s"
1279  : "https://%s",
1280  s5r->leho);
1281  if (0 == strncmp (leho_host,
1282  hdr_val,
1283  strlen (leho_host)))
1284  {
1285  GNUNET_asprintf (&new_location,
1286  "%s%s",
1287  (GNUNET_YES != s5r->is_tls) //(HTTPS_PORT != s5r->port)
1288  ? "http://"
1289  : "https://",
1290  s5r->domain);
1291  hdr_val = new_location;
1292  }
1293  GNUNET_free (leho_host);
1294  }
1295 
1296  /* MHD does not allow certain characters in values, remove those */
1297  if (NULL != (tok = strchr (hdr_val, '\n')))
1298  *tok = '\0';
1299  if (NULL != (tok = strchr (hdr_val, '\r')))
1300  *tok = '\0';
1301  if (NULL != (tok = strchr (hdr_val, '\t')))
1302  *tok = '\0';
1303  if (0 != strlen (hdr_val)) /* Rely in MHD to set those */
1304  {
1306  "Adding header %s: %s to MHD response\n",
1307  hdr_type,
1308  hdr_val);
1309  header = GNUNET_new (struct HttpResponseHeader);
1310  header->type = GNUNET_strdup (hdr_type);
1311  header->value = GNUNET_strdup (hdr_val);
1313  s5r->header_tail,
1314  header);
1315  }
1316  cleanup:
1317  GNUNET_free (ndup);
1318  GNUNET_free_non_null (new_cookie_hdr);
1319  GNUNET_free_non_null (new_location);
1320  return bytes;
1321 }
struct HttpResponseHeader * header_head
Headers from response.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
char * value
Header value.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
char * type
Header type.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
A header list.
struct HttpResponseHeader * header_tail
Headers from response.
int ssl_checked
X.509 Certificate status.
static int check_ssl_certificate(struct Socks5Request *s5r)
Check that the website has presented us with a valid X.509 certificate.
#define GNUNET_memcpy(dst, src, n)
char * domain
the domain name to server (only important for TLS)
static void cleanup(void *cls)
Function scheduled as very last function, cleans up after us.
static unsigned int size
Size of the "table".
Definition: peer.c:67
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
char * leho
DNS Legacy Host Name as given by GNS, NULL if not given.
#define GNUNET_log(kind,...)
int is_tls
This is (probably) a TLS connection.
#define GNUNET_YES
Definition: gnunet_common.h:80
A structure for socks requests.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_mhd_response_from_s5r()

static int create_mhd_response_from_s5r ( struct Socks5Request s5r)
static

Create an MHD response object in s5r matching the information we got from curl.

Parameters
s5rthe request for which we convert the response
Returns
GNUNET_OK on success, GNUNET_SYSERR if response was already initialized before

Definition at line 1333 of file gnunet-gns-proxy.c.

References Socks5Request::con, Socks5Request::curl, Socks5Request::domain, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, Socks5Request::header_head, IO_BUFFERSIZE, mhd_content_cb(), HttpResponseHeader::next, Socks5Request::response, Socks5Request::response_code, Socks5Request::suspended, and Socks5Request::url.

Referenced by curl_download_cb(), and curl_task_download().

1334 {
1335  long resp_code;
1336  double content_length;
1337 
1338  if (NULL != s5r->response)
1339  {
1341  "Response already set!\n");
1342  return GNUNET_SYSERR;
1343  }
1344 
1345  GNUNET_break (CURLE_OK ==
1346  curl_easy_getinfo (s5r->curl,
1347  CURLINFO_RESPONSE_CODE,
1348  &resp_code));
1349  GNUNET_break (CURLE_OK ==
1350  curl_easy_getinfo (s5r->curl,
1351  CURLINFO_CONTENT_LENGTH_DOWNLOAD,
1352  &content_length));
1354  "Creating MHD response with code %d and size %d for %s%s\n",
1355  (int) resp_code,
1356  (int) content_length,
1357  s5r->domain,
1358  s5r->url);
1359  s5r->response_code = resp_code;
1360  s5r->response = MHD_create_response_from_callback ((-1 == content_length)
1361  ? MHD_SIZE_UNKNOWN
1362  : content_length,
1363  IO_BUFFERSIZE,
1364  &mhd_content_cb,
1365  s5r,
1366  NULL);
1367  for (struct HttpResponseHeader *header = s5r->header_head;
1368  NULL != header;
1369  header = header->next)
1370  {
1371  if (0 == strcasecmp (header->type,
1372  MHD_HTTP_HEADER_CONTENT_LENGTH))
1373  continue; /* MHD won't let us mess with those, for good reason */
1374  if ( (0 == strcasecmp (header->type,
1375  MHD_HTTP_HEADER_TRANSFER_ENCODING)) &&
1376  ( (0 == strcasecmp (header->value,
1377  "identity")) ||
1378  (0 == strcasecmp (header->value,
1379  "chunked")) ) )
1380  continue; /* MHD won't let us mess with those, for good reason */
1381  if (MHD_YES !=
1382  MHD_add_response_header (s5r->response,
1383  header->type,
1384  header->value))
1385  {
1386  GNUNET_break (0);
1388  "Failed to add header `%s:%s'\n",
1389  header->type,
1390  header->value);
1391  }
1392  }
1393  /* force connection to be closed after each request, as we
1394  do not support HTTP pipelining (yet, FIXME!) */
1395  /*GNUNET_break (MHD_YES ==
1396  MHD_add_response_header (s5r->response,
1397  MHD_HTTP_HEADER_CONNECTION,
1398  "close"));*/
1399  MHD_resume_connection (s5r->con);
1400  s5r->suspended = GNUNET_NO;
1401  return GNUNET_OK;
1402 }
struct HttpResponseHeader * header_head
Headers from response.
struct MHD_Connection * con
MHD connection for this request.
#define IO_BUFFERSIZE
Size of the buffer for the data upload / download.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct HttpResponseHeader * next
DLL.
A header list.
int suspended
Did we suspend MHD processing?
char * domain
the domain name to server (only important for TLS)
struct MHD_Response * response
MHD response object for this request.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static ssize_t mhd_content_cb(void *cls, uint64_t pos, char *buf, size_t max)
Callback for MHD response generation.
#define GNUNET_log(kind,...)
char * url
The URL to fetch.
unsigned int response_code
HTTP response code to give to MHD for the response.
CURL * curl
Handle to cURL.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ curl_download_cb()

static size_t curl_download_cb ( void *  ptr,
size_t  size,
size_t  nmemb,
void *  ctx 
)
static

Handle response payload data from cURL.

Copies it into our io_buf to make it available to MHD.

Parameters
ptrpointer to the data
sizenumber of blocks of data
nmembblocksize
ctxour struct Socks5Request *
Returns
number of bytes handled

Definition at line 1416 of file gnunet-gns-proxy.c.

References Socks5Request::con, create_mhd_response_from_s5r(), ctx, Socks5Request::curl_paused, Socks5Request::domain, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_NO, GNUNET_OK, GNUNET_YES, Socks5Request::hd, Socks5Request::io_buf, Socks5Request::io_len, Socks5Request::response, run_mhd_now(), SOCKS5_SOCKET_DOWNLOAD_STARTED, SOCKS5_SOCKET_UPLOAD_DONE, SOCKS5_SOCKET_UPLOAD_STARTED, Socks5Request::state, Socks5Request::suspended, and Socks5Request::url.

Referenced by create_response().

1420 {
1421  struct Socks5Request *s5r = ctx;
1422  size_t total = size * nmemb;
1423 
1425  "Receiving %ux%u bytes for `%s%s' from cURL to download\n",
1426  (unsigned int) size,
1427  (unsigned int) nmemb,
1428  s5r->domain,
1429  s5r->url);
1430  if (NULL == s5r->response)
1433  if ( (SOCKS5_SOCKET_UPLOAD_DONE == s5r->state) &&
1434  (0 == s5r->io_len))
1435  {
1437  "Previous upload finished... starting DOWNLOAD.\n");
1439  }
1440  if ( (SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state) ||
1441  (SOCKS5_SOCKET_UPLOAD_DONE == s5r->state) )
1442  {
1443  /* we're still not done with the upload, do not yet
1444  start the download, the IO buffer is still full
1445  with upload data. */
1447  "Pausing CURL download `%s%s', waiting for UPLOAD to finish\n",
1448  s5r->domain,
1449  s5r->url);
1450  s5r->curl_paused = GNUNET_YES;
1451  return CURL_WRITEFUNC_PAUSE; /* not yet ready for data download */
1452  }
1453  if (sizeof (s5r->io_buf) - s5r->io_len < total)
1454  {
1456  "Pausing CURL `%s%s' download, not enough space %llu %llu %llu\n",
1457  s5r->domain,
1458  s5r->url,
1459  (unsigned long long) sizeof (s5r->io_buf),
1460  (unsigned long long) s5r->io_len,
1461  (unsigned long long) total);
1462  s5r->curl_paused = GNUNET_YES;
1463  return CURL_WRITEFUNC_PAUSE; /* not enough space */
1464  }
1465  GNUNET_memcpy (&s5r->io_buf[s5r->io_len],
1466  ptr,
1467  total);
1468  s5r->io_len += total;
1469  if (GNUNET_YES == s5r->suspended)
1470  {
1471  MHD_resume_connection (s5r->con);
1472  s5r->suspended = GNUNET_NO;
1473  }
1475  "Received %llu bytes of payload via cURL from %s\n",
1476  (unsigned long long) total,
1477  s5r->domain);
1478  if (s5r->io_len == total)
1479  run_mhd_now (s5r->hd);
1480  return total;
1481 }
struct MHD_Connection * con
MHD connection for this request.
static int create_mhd_response_from_s5r(struct Socks5Request *s5r)
Create an MHD response object in s5r matching the information we got from curl.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int curl_paused
Did we pause CURL processing?
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
We&#39;ve started receiving upload data from MHD.
We&#39;ve finished receiving upload data from MHD.
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
size_t io_len
Number of bytes already in the IO buffer.
#define GNUNET_memcpy(dst, src, n)
int suspended
Did we suspend MHD processing?
enum SocksPhase state
The socks state.
struct MhdHttpList * hd
MHD HTTP instance handling this request, NULL for none.
char * domain
the domain name to server (only important for TLS)
struct MHD_Response * response
MHD response object for this request.
static unsigned int size
Size of the "table".
Definition: peer.c:67
We&#39;ve finished uploading data via CURL and can now download.
#define GNUNET_log(kind,...)
char io_buf[CURL_MAX_WRITE_SIZE]
Buffer we use for moving data between MHD and curl (in both directions).
#define GNUNET_YES
Definition: gnunet_common.h:80
char * url
The URL to fetch.
A structure for socks requests.
static void run_mhd_now(struct MhdHttpList *hd)
Run MHD now, we have extra data ready for the callback.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ curl_upload_cb()

static size_t curl_upload_cb ( void *  buf,
size_t  size,
size_t  nmemb,
void *  cls 
)
static

cURL callback for uploaded (PUT/POST) data.

Copies it into our io_buf to make it available to MHD.

Parameters
bufwhere to write the data
sizenumber of bytes per member
nmembnumber of members available in buf
clsour struct Socks5Request that generated the data
Returns
number of bytes copied to buf

Definition at line 1495 of file gnunet-gns-proxy.c.

References Socks5Request::curl, Socks5Request::curl_paused, curl_task_download(), Socks5Request::domain, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_MIN, GNUNET_NO, GNUNET_YES, Socks5Request::hd, Socks5Request::io_buf, Socks5Request::io_len, len, run_mhd_now(), SOCKS5_SOCKET_DOWNLOAD_STARTED, SOCKS5_SOCKET_UPLOAD_DONE, SOCKS5_SOCKET_UPLOAD_STARTED, Socks5Request::state, and Socks5Request::url.

Referenced by create_response().

1499 {
1500  struct Socks5Request *s5r = cls;
1501  size_t len = size * nmemb;
1502  size_t to_copy;
1503 
1505  "Receiving %ux%u bytes for `%s%s' from cURL to upload\n",
1506  (unsigned int) size,
1507  (unsigned int) nmemb,
1508  s5r->domain,
1509  s5r->url);
1510 
1511  if ( (0 == s5r->io_len) &&
1512  (SOCKS5_SOCKET_UPLOAD_DONE != s5r->state) )
1513  {
1515  "Pausing CURL UPLOAD %s%s, need more data\n",
1516  s5r->domain,
1517  s5r->url);
1518  return CURL_READFUNC_PAUSE;
1519  }
1520  if ( (0 == s5r->io_len) &&
1521  (SOCKS5_SOCKET_UPLOAD_DONE == s5r->state) )
1522  {
1524  if (GNUNET_YES == s5r->curl_paused)
1525  {
1526  s5r->curl_paused = GNUNET_NO;
1527  curl_easy_pause (s5r->curl,
1528  CURLPAUSE_CONT);
1529  }
1531  "Completed CURL UPLOAD %s%s\n",
1532  s5r->domain,
1533  s5r->url);
1534  return 0; /* upload finished, can now download */
1535  }
1536  if ( (SOCKS5_SOCKET_UPLOAD_STARTED != s5r->state) &&
1537  (SOCKS5_SOCKET_UPLOAD_DONE != s5r->state) )
1538  {
1539  GNUNET_break (0);
1540  return CURL_READFUNC_ABORT;
1541  }
1542  to_copy = GNUNET_MIN (s5r->io_len,
1543  len);
1544  GNUNET_memcpy (buf,
1545  s5r->io_buf,
1546  to_copy);
1547  memmove (s5r->io_buf,
1548  &s5r->io_buf[to_copy],
1549  s5r->io_len - to_copy);
1550  s5r->io_len -= to_copy;
1551  if (s5r->io_len + to_copy == sizeof (s5r->io_buf))
1552  run_mhd_now (s5r->hd); /* got more space for upload now */
1553  return to_copy;
1554 }
int curl_paused
Did we pause CURL processing?
#define GNUNET_NO
Definition: gnunet_common.h:81
We&#39;ve started receiving upload data from MHD.
We&#39;ve finished receiving upload data from MHD.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
size_t io_len
Number of bytes already in the IO buffer.
#define GNUNET_memcpy(dst, src, n)
enum SocksPhase state
The socks state.
struct MhdHttpList * hd
MHD HTTP instance handling this request, NULL for none.
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:83
char * domain
the domain name to server (only important for TLS)
static char buf[2048]
static unsigned int size
Size of the "table".
Definition: peer.c:67
We&#39;ve finished uploading data via CURL and can now download.
#define GNUNET_log(kind,...)
char io_buf[CURL_MAX_WRITE_SIZE]
Buffer we use for moving data between MHD and curl (in both directions).
#define GNUNET_YES
Definition: gnunet_common.h:80
char * url
The URL to fetch.
A structure for socks requests.
static void run_mhd_now(struct MhdHttpList *hd)
Run MHD now, we have extra data ready for the callback.
CURL * curl
Handle to cURL.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ curl_task_download()

static void curl_task_download ( void *  cls)
static

Task that is run when we are ready to receive more data from curl.

Parameters
clsclosure
clsclosure, NULL

Definition at line 1652 of file gnunet-gns-proxy.c.

References create_mhd_response_from_s5r(), curl_download_prepare(), curl_failure_response, curl_multi, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_cancel(), GNUNET_YES, msg, run_mhd_now(), and SOCKS5_SOCKET_DOWNLOAD_DONE.

Referenced by curl_download_prepare(), and curl_upload_cb().

1653 {
1654  int running;
1655  int msgnum;
1656  struct CURLMsg *msg;
1657  CURLMcode mret;
1658  struct Socks5Request *s5r;
1659 
1660  curl_download_task = NULL;
1662  "Running CURL interaction\n");
1663  do
1664  {
1665  running = 0;
1666  mret = curl_multi_perform (curl_multi,
1667  &running);
1669  "Checking CURL multi status: %d\n",
1670  mret);
1671  while (NULL != (msg = curl_multi_info_read (curl_multi,
1672  &msgnum)))
1673  {
1674  GNUNET_break (CURLE_OK ==
1675  curl_easy_getinfo (msg->easy_handle,
1676  CURLINFO_PRIVATE,
1677  (char **) &s5r ));
1678  if (NULL == s5r)
1679  {
1680  GNUNET_break (0);
1681  continue;
1682  }
1683  switch (msg->msg)
1684  {
1685  case CURLMSG_NONE:
1686  /* documentation says this is not used */
1687  GNUNET_break (0);
1688  break;
1689  case CURLMSG_DONE:
1690  switch (msg->data.result)
1691  {
1692  case CURLE_OK:
1693  case CURLE_GOT_NOTHING:
1695  "CURL download %s%s completed.\n",
1696  s5r->domain,
1697  s5r->url);
1698  if (NULL == s5r->response)
1699  {
1702  }
1704  if (GNUNET_YES == s5r->suspended)
1705  {
1706  MHD_resume_connection (s5r->con);
1707  s5r->suspended = GNUNET_NO;
1708  }
1709  run_mhd_now (s5r->hd);
1710  break;
1711  default:
1713  "Download curl %s%s failed: %s\n",
1714  s5r->domain,
1715  s5r->url,
1716  curl_easy_strerror (msg->data.result));
1717  /* FIXME: indicate error somehow? close MHD connection badly as well? */
1719  if (GNUNET_YES == s5r->suspended)
1720  {
1721  MHD_resume_connection (s5r->con);
1722  s5r->suspended = GNUNET_NO;
1723  }
1724  run_mhd_now (s5r->hd);
1725  break;
1726  }
1727  if (NULL == s5r->response)
1729  break;
1730  case CURLMSG_LAST:
1731  /* documentation says this is not used */
1732  GNUNET_break (0);
1733  break;
1734  default:
1735  /* unexpected status code */
1736  GNUNET_break (0);
1737  break;
1738  }
1739  };
1740  } while (mret == CURLM_CALL_MULTI_PERFORM);
1741  if (CURLM_OK != mret)
1743  "%s failed at %s:%d: `%s'\n",
1744  "curl_multi_perform", __FILE__, __LINE__,
1745  curl_multi_strerror (mret));
1746  if (0 == running)
1747  {
1749  "Suspending cURL multi loop, no more events pending\n");
1750  if (NULL != curl_download_task)
1751  {
1753  curl_download_task = NULL;
1754  }
1755  return; /* nothing more in progress */
1756  }
1758 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct MHD_Connection * con
MHD connection for this request.
static int create_mhd_response_from_s5r(struct Socks5Request *s5r)
Create an MHD response object in s5r matching the information we got from curl.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static struct MHD_Response * curl_failure_response
Response we return on cURL failures.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
int suspended
Did we suspend MHD processing?
enum SocksPhase state
The socks state.
struct MhdHttpList * hd
MHD HTTP instance handling this request, NULL for none.
char * domain
the domain name to server (only important for TLS)
struct MHD_Response * response
MHD response object for this request.
static struct GNUNET_SCHEDULER_Task * curl_download_task
The cURL download task (curl multi API).
static void curl_download_prepare()
Ask cURL for the select() sets and schedule cURL operations.
We&#39;ve finished receiving download data from cURL.
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:80
char * url
The URL to fetch.
A structure for socks requests.
static CURLM * curl_multi
The cURL multi handle.
static void run_mhd_now(struct MhdHttpList *hd)
Run MHD now, we have extra data ready for the callback.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
Here is the call graph for this function:
Here is the caller graph for this function:

◆ con_val_iter()

static int con_val_iter ( void *  cls,
enum MHD_ValueKind  kind,
const char *  key,
const char *  value 
)
static

Read HTTP request header field from the request.

Copies the fields over to the 'headers' that will be given to curl. However, 'Host' is substituted with the LEHO if present. We also change the 'Connection' header value to "close" as the proxy does not support pipelining.

Parameters
clsour struct Socks5Request
kindvalue kind
keyfield key
valuefield value
Returns
#MHD_YES to continue to iterate

Definition at line 1778 of file gnunet-gns-proxy.c.

References GNUNET_asprintf(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, Socks5Request::headers, and Socks5Request::leho.

Referenced by create_response().

1782 {
1783  struct Socks5Request *s5r = cls;
1784  char *hdr;
1785 
1786  if ( (0 == strcasecmp (MHD_HTTP_HEADER_HOST,
1787  key)) &&
1788  (NULL != s5r->leho) )
1789  value = s5r->leho;
1790  GNUNET_asprintf (&hdr,
1791  "%s: %s",
1792  key,
1793  value);
1795  "Adding HEADER `%s' to HTTP request\n",
1796  hdr);
1797  s5r->headers = curl_slist_append (s5r->headers,
1798  hdr);
1799  GNUNET_free (hdr);
1800  return MHD_YES;
1801 }
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
static char * value
Value of the record to add/remove.
struct curl_slist * headers
HTTP request headers for the curl request.
struct GNUNET_HashCode key
The key used in the DHT.
char * leho
DNS Legacy Host Name as given by GNS, NULL if not given.
#define GNUNET_log(kind,...)
A structure for socks requests.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_response()

static int create_response ( void *  cls,
struct MHD_Connection *  con,
const char *  url,
const char *  meth,
const char *  ver,
const char *  upload_data,
size_t *  upload_data_size,
void **  con_cls 
)
static

Main MHD callback for handling requests.

Parameters
clsunused
conMHD connection handle
urlthe url in the request
meththe HTTP method used ("GET", "PUT", etc.)
verthe HTTP version string (i.e. "HTTP/1.1")
upload_datathe data being uploaded (excluding HEADERS, for a POST that fits into memory and that is encoded with a supported encoding, the POST data will NOT be given in upload_data and is instead available as part of MHD_get_connection_values; very large POST data will be made available incrementally in upload_data)
upload_data_sizeset initially to the size of the upload_data provided; the method must update this value to the number of bytes NOT processed;
con_clspointer to location where we store the struct Request
Returns
#MHD_YES if the connection was handled successfully, #MHD_NO if the socket must be closed due to a serious error while handling the request

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

Definition at line 1828 of file gnunet-gns-proxy.c.

References _, Socks5Request::con, con_val_iter(), Socks5Request::curl, curl_check_hdr(), curl_download_cb(), curl_download_prepare(), curl_failure_response, curl_multi, Socks5Request::curl_paused, curl_upload_cb(), Socks5Request::destination_address, Socks5Request::domain, GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_memcpy, GNUNET_MIN, GNUNET_NO, GNUNET_snprintf(), GNUNET_YES, Socks5Request::hd, Socks5Request::headers, Socks5Request::hosts, Socks5Request::io_buf, Socks5Request::io_len, Socks5Request::is_gns, Socks5Request::is_tls, Socks5Request::leho, Socks5Request::num_danes, Socks5Request::port, port, Socks5Request::response, Socks5Request::response_code, run_mhd_now(), SOCKS5_SOCKET_DOWNLOAD_STARTED, SOCKS5_SOCKET_UPLOAD_DONE, SOCKS5_SOCKET_UPLOAD_STARTED, SOCKS5_SOCKET_WITH_MHD, Socks5Request::state, Socks5Request::suspended, and Socks5Request::url.

Referenced by lookup_ssl_httpd(), and run().

1836 {
1837  struct Socks5Request *s5r = *con_cls;
1838  char *curlurl;
1839  char ipstring[INET6_ADDRSTRLEN];
1840  char ipaddr[INET6_ADDRSTRLEN + 2];
1841  const struct sockaddr *sa;
1842  const struct sockaddr_in *s4;
1843  const struct sockaddr_in6 *s6;
1844  uint16_t port;
1845  size_t left;
1846 
1847  if (NULL == s5r)
1848  {
1849  GNUNET_break (0);
1850  return MHD_NO;
1851  }
1852  s5r->con = con;
1853  /* Fresh connection. */
1854  if (SOCKS5_SOCKET_WITH_MHD == s5r->state)
1855  {
1856  /* first time here, initialize curl handle */
1857  if (s5r->is_gns)
1858  {
1859  sa = (const struct sockaddr *) &s5r->destination_address;
1860  switch (sa->sa_family)
1861  {
1862  case AF_INET:
1863  s4 = (const struct sockaddr_in *) &s5r->destination_address;
1864  if (NULL == inet_ntop (AF_INET,
1865  &s4->sin_addr,
1866  ipstring,
1867  sizeof (ipstring)))
1868  {
1869  GNUNET_break (0);
1870  return MHD_NO;
1871  }
1872  GNUNET_snprintf (ipaddr,
1873  sizeof (ipaddr),
1874  "%s",
1875  ipstring);
1876  port = ntohs (s4->sin_port);
1877  break;
1878  case AF_INET6:
1879  s6 = (const struct sockaddr_in6 *) &s5r->destination_address;
1880  if (NULL == inet_ntop (AF_INET6,
1881  &s6->sin6_addr,
1882  ipstring,
1883  sizeof (ipstring)))
1884  {
1885  GNUNET_break (0);
1886  return MHD_NO;
1887  }
1888  GNUNET_snprintf (ipaddr,
1889  sizeof (ipaddr),
1890  "%s",
1891  ipstring);
1892  port = ntohs (s6->sin6_port);
1893  break;
1894  default:
1895  GNUNET_break (0);
1896  return MHD_NO;
1897  }
1898  }
1899  else
1900  {
1901  port = s5r->port;
1902  }
1903  if (NULL == s5r->curl)
1904  s5r->curl = curl_easy_init ();
1905  if (NULL == s5r->curl)
1906  return MHD_queue_response (con,
1907  MHD_HTTP_INTERNAL_SERVER_ERROR,
1909  curl_easy_setopt (s5r->curl,
1910  CURLOPT_HEADERFUNCTION,
1911  &curl_check_hdr);
1912  curl_easy_setopt (s5r->curl,
1913  CURLOPT_HEADERDATA,
1914  s5r);
1915  curl_easy_setopt (s5r->curl,
1916  CURLOPT_FOLLOWLOCATION,
1917  0);
1918  if (s5r->is_gns)
1919  curl_easy_setopt (s5r->curl,
1920  CURLOPT_IPRESOLVE,
1921  CURL_IPRESOLVE_V4);
1922  curl_easy_setopt (s5r->curl,
1923  CURLOPT_CONNECTTIMEOUT,
1924  600L);
1925  curl_easy_setopt (s5r->curl,
1926  CURLOPT_TIMEOUT,
1927  600L);
1928  curl_easy_setopt (s5r->curl,
1929  CURLOPT_NOSIGNAL,
1930  1L);
1931  curl_easy_setopt (s5r->curl,
1932  CURLOPT_HTTP_CONTENT_DECODING,
1933  0);
1934  curl_easy_setopt (s5r->curl,
1935  CURLOPT_NOSIGNAL,
1936  1L);
1937  curl_easy_setopt (s5r->curl,
1938  CURLOPT_PRIVATE,
1939  s5r);
1940  curl_easy_setopt (s5r->curl,
1941  CURLOPT_VERBOSE,
1942  0L);
1948  if (NULL != s5r->leho)
1949  {
1950  char *curl_hosts;
1951 
1952  GNUNET_asprintf (&curl_hosts,
1953  "%s:%d:%s",
1954  s5r->leho,
1955  port,
1956  ipaddr);
1957  s5r->hosts = curl_slist_append (NULL,
1958  curl_hosts);
1959  curl_easy_setopt (s5r->curl,
1960  CURLOPT_RESOLVE,
1961  s5r->hosts);
1962  GNUNET_free (curl_hosts);
1963  }
1964  if (s5r->is_gns)
1965  {
1966  GNUNET_asprintf (&curlurl,
1967  (GNUNET_YES != s5r->is_tls) //(HTTPS_PORT != s5r->port)
1968  ? "http://%s:%d%s"
1969  : "https://%s:%d%s",
1970  (NULL != s5r->leho)
1971  ? s5r->leho
1972  : ipaddr,
1973  port,
1974  s5r->url);
1975  }
1976  else
1977  {
1978  GNUNET_asprintf (&curlurl,
1979  (GNUNET_YES != s5r->is_tls) //(HTTPS_PORT != s5r->port)
1980  ? "http://%s:%d%s"
1981  : "https://%s:%d%s",
1982  s5r->domain,
1983  port,
1984  s5r->url);
1985  }
1986  curl_easy_setopt (s5r->curl,
1987  CURLOPT_URL,
1988  curlurl);
1990  "Launching %s CURL interaction, fetching `%s'\n",
1991  (s5r->is_gns) ? "GNS" : "DNS",
1992  curlurl);
1993  GNUNET_free (curlurl);
1994  if (0 == strcasecmp (meth,
1995  MHD_HTTP_METHOD_PUT))
1996  {
1998  curl_easy_setopt (s5r->curl,
1999  CURLOPT_UPLOAD,
2000  1L);
2001  curl_easy_setopt (s5r->curl,
2002  CURLOPT_WRITEFUNCTION,
2003  &curl_download_cb);
2004  curl_easy_setopt (s5r->curl,
2005  CURLOPT_WRITEDATA,
2006  s5r);
2007  GNUNET_assert (CURLE_OK ==
2008  curl_easy_setopt (s5r->curl,
2009  CURLOPT_READFUNCTION,
2010  &curl_upload_cb));
2011  curl_easy_setopt (s5r->curl,
2012  CURLOPT_READDATA,
2013  s5r);
2014  {
2015  const char *us;
2016  long upload_size = 0;
2017 
2018  us = MHD_lookup_connection_value (con,
2019  MHD_HEADER_KIND,
2020  MHD_HTTP_HEADER_CONTENT_LENGTH);
2021  if ( (1 == sscanf (us,
2022  "%ld",
2023  &upload_size)) &&
2024  (upload_size >= 0) )
2025  {
2026  curl_easy_setopt (s5r->curl,
2027  CURLOPT_INFILESIZE,
2028  upload_size);
2029  }
2030  }
2031  }
2032  else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_POST))
2033  {
2035  curl_easy_setopt (s5r->curl,
2036  CURLOPT_POST,
2037  1L);
2038  curl_easy_setopt (s5r->curl,
2039  CURLOPT_WRITEFUNCTION,
2040  &curl_download_cb);
2041  curl_easy_setopt (s5r->curl,
2042  CURLOPT_WRITEDATA,
2043  s5r);
2044  curl_easy_setopt (s5r->curl,
2045  CURLOPT_READFUNCTION,
2046  &curl_upload_cb);
2047  curl_easy_setopt (s5r->curl,
2048  CURLOPT_READDATA,
2049  s5r);
2050  {
2051  const char *us;
2052  long upload_size;
2053 
2054  upload_size = 0;
2055  us = MHD_lookup_connection_value (con,
2056  MHD_HEADER_KIND,
2057  MHD_HTTP_HEADER_CONTENT_LENGTH);
2058  if ( (NULL != us) &&
2059  (1 == sscanf (us,
2060  "%ld",
2061  &upload_size)) &&
2062  (upload_size >= 0) )
2063  {
2064  curl_easy_setopt (s5r->curl,
2065  CURLOPT_INFILESIZE,
2066  upload_size);
2067  } else {
2068  curl_easy_setopt (s5r->curl,
2069  CURLOPT_INFILESIZE,
2070  upload_size);
2071  }
2072  }
2073  }
2074  else if (0 == strcasecmp (meth,
2075  MHD_HTTP_METHOD_HEAD))
2076  {
2078  curl_easy_setopt (s5r->curl,
2079  CURLOPT_NOBODY,
2080  1L);
2081  }
2082  else if (0 == strcasecmp (meth,
2083  MHD_HTTP_METHOD_OPTIONS))
2084  {
2086  curl_easy_setopt (s5r->curl,
2087  CURLOPT_CUSTOMREQUEST,
2088  "OPTIONS");
2089  curl_easy_setopt (s5r->curl,
2090  CURLOPT_WRITEFUNCTION,
2091  &curl_download_cb);
2092  curl_easy_setopt (s5r->curl,
2093  CURLOPT_WRITEDATA,
2094  s5r);
2095 
2096  }
2097  else if (0 == strcasecmp (meth,
2098  MHD_HTTP_METHOD_GET))
2099  {
2101  curl_easy_setopt (s5r->curl,
2102  CURLOPT_HTTPGET,
2103  1L);
2104  curl_easy_setopt (s5r->curl,
2105  CURLOPT_WRITEFUNCTION,
2106  &curl_download_cb);
2107  curl_easy_setopt (s5r->curl,
2108  CURLOPT_WRITEDATA,
2109  s5r);
2110  }
2111  else if (0 == strcasecmp (meth,
2112  MHD_HTTP_METHOD_DELETE))
2113  {
2115  curl_easy_setopt (s5r->curl,
2116  CURLOPT_CUSTOMREQUEST,
2117  "DELETE");
2118  curl_easy_setopt (s5r->curl,
2119  CURLOPT_WRITEFUNCTION,
2120  &curl_download_cb);
2121  curl_easy_setopt (s5r->curl,
2122  CURLOPT_WRITEDATA,
2123  s5r);
2124  }
2125  else
2126  {
2128  _("Unsupported HTTP method `%s'\n"),
2129  meth);
2130  curl_easy_cleanup (s5r->curl);
2131  s5r->curl = NULL;
2132  return MHD_NO;
2133  }
2134 
2135  if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_0))
2136  {
2137  curl_easy_setopt (s5r->curl,
2138  CURLOPT_HTTP_VERSION,
2139  CURL_HTTP_VERSION_1_0);
2140  }
2141  else if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_1))
2142  {
2143  curl_easy_setopt (s5r->curl,
2144  CURLOPT_HTTP_VERSION,
2145  CURL_HTTP_VERSION_1_1);
2146  }
2147  else
2148  {
2149  curl_easy_setopt (s5r->curl,
2150  CURLOPT_HTTP_VERSION,
2151  CURL_HTTP_VERSION_NONE);
2152  }
2153 
2154  if (GNUNET_YES == s5r->is_tls) //(HTTPS_PORT == s5r->port)
2155  {
2156  curl_easy_setopt (s5r->curl,
2157  CURLOPT_USE_SSL,
2158  CURLUSESSL_ALL);
2159  if (0 < s5r->num_danes)
2160  curl_easy_setopt (s5r->curl,
2161  CURLOPT_SSL_VERIFYPEER,
2162  0L);
2163  else
2164  curl_easy_setopt (s5r->curl,
2165  CURLOPT_SSL_VERIFYPEER,
2166  1L);
2167  /* Disable cURL checking the hostname, as we will check ourselves
2168  as only we have the domain name or the LEHO or the DANE record */
2169  curl_easy_setopt (s5r->curl,
2170  CURLOPT_SSL_VERIFYHOST,
2171  0L);
2172  }
2173  else
2174  {
2175  curl_easy_setopt (s5r->curl,
2176  CURLOPT_USE_SSL,
2177  CURLUSESSL_NONE);
2178  }
2179 
2180  if (CURLM_OK !=
2181  curl_multi_add_handle (curl_multi,
2182  s5r->curl))
2183  {
2184  GNUNET_break (0);
2185  curl_easy_cleanup (s5r->curl);
2186  s5r->curl = NULL;
2187  return MHD_NO;
2188  }
2189  MHD_get_connection_values (con,
2190  MHD_HEADER_KIND,
2191  (MHD_KeyValueIterator) &con_val_iter,
2192  s5r);
2193  curl_easy_setopt (s5r->curl,
2194  CURLOPT_HTTPHEADER,
2195  s5r->headers);
2197  return MHD_YES;
2198  }
2199 
2200  /* continuing to process request */
2201  if (0 != *upload_data_size)
2202  {
2204  "Processing %u bytes UPLOAD\n",
2205  (unsigned int) *upload_data_size);
2206 
2207  /* FIXME: This must be set or a header with Transfer-Encoding: chunked. Else
2208  * upload callback is not called!
2209  */
2210  curl_easy_setopt (s5r->curl,
2211  CURLOPT_POSTFIELDSIZE,
2212  *upload_data_size);
2213 
2214  left = GNUNET_MIN (*upload_data_size,
2215  sizeof (s5r->io_buf) - s5r->io_len);
2216  GNUNET_memcpy (&s5r->io_buf[s5r->io_len],
2217  upload_data,
2218  left);
2219  s5r->io_len += left;
2220  *upload_data_size -= left;
2221  GNUNET_assert (NULL != s5r->curl);
2222  if (GNUNET_YES == s5r->curl_paused)
2223  {
2224  s5r->curl_paused = GNUNET_NO;
2225  curl_easy_pause (s5r->curl,
2226  CURLPAUSE_CONT);
2227  }
2228  return MHD_YES;
2229  }
2230  if (SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state)
2231  {
2233  "Finished processing UPLOAD\n");
2235  }
2236  if (NULL == s5r->response)
2237  {
2239  "Waiting for HTTP response for %s%s...\n",
2240  s5r->domain,
2241  s5r->url);
2242  MHD_suspend_connection (con);
2243  s5r->suspended = GNUNET_YES;
2244  return MHD_YES;
2245  }
2247  "Queueing response for %s%s with MHD\n",
2248  s5r->domain,
2249  s5r->url);
2250  run_mhd_now (s5r->hd);
2251  return MHD_queue_response (con,
2252  s5r->response_code,
2253  s5r->response);
2254 }
Socket has been passed to MHD, do not close it anymore.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
struct MHD_Connection * con
MHD connection for this request.
static size_t curl_check_hdr(void *buffer, size_t size, size_t nmemb, void *cls)
We&#39;re getting an HTTP response header from cURL.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static struct MHD_Response * curl_failure_response
Response we return on cURL failures.
int curl_paused
Did we pause CURL processing?
#define GNUNET_NO
Definition: gnunet_common.h:81
We&#39;ve started receiving upload data from MHD.
We&#39;ve finished receiving upload data from MHD.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
size_t io_len
Number of bytes already in the IO buffer.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
static uint16_t port
The port the proxy is running on (default 7777)
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#define GNUNET_memcpy(dst, src, n)
int suspended
Did we suspend MHD processing?
unsigned int num_danes
Number of entries used in dane_data_len and dane_data.
struct curl_slist * headers
HTTP request headers for the curl request.
enum SocksPhase state
The socks state.
struct MhdHttpList * hd
MHD HTTP instance handling this request, NULL for none.
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:83
char * domain
the domain name to server (only important for TLS)
struct MHD_Response * response
MHD response object for this request.
uint16_t port
Desired destination port.
struct sockaddr_storage destination_address
Once known, what&#39;s the target address for the connection?
struct curl_slist * hosts
DNS->IP mappings resolved through GNS.
static int con_val_iter(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Read HTTP request header field from the request.
static size_t curl_download_cb(void *ptr, size_t size, size_t nmemb, void *ctx)
Handle response payload data from cURL.
We&#39;ve finished uploading data via CURL and can now download.
int is_gns
Was the hostname resolved via GNS?
char * leho
DNS Legacy Host Name as given by GNS, NULL if not given.
static void curl_download_prepare()
Ask cURL for the select() sets and schedule cURL operations.
#define GNUNET_log(kind,...)
char io_buf[CURL_MAX_WRITE_SIZE]
Buffer we use for moving data between MHD and curl (in both directions).
int is_tls
This is (probably) a TLS connection.
#define GNUNET_YES
Definition: gnunet_common.h:80
char * url
The URL to fetch.
A structure for socks requests.
static CURLM * curl_multi
The cURL multi handle.
static void run_mhd_now(struct MhdHttpList *hd)
Run MHD now, we have extra data ready for the callback.
unsigned int response_code
HTTP response code to give to MHD for the response.
static size_t curl_upload_cb(void *buf, size_t size, size_t nmemb, void *cls)
cURL callback for uploaded (PUT/POST) data.
#define GNUNET_free(ptr)
Wrapper around free.
CURL * curl
Handle to cURL.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mhd_completed_cb()

static void mhd_completed_cb ( void *  cls,
struct MHD_Connection *  connection,
void **  con_cls,
enum MHD_RequestTerminationCode  toe 
)
static

Function called when MHD decides that we are done with a request.

Parameters
clsNULL
connectionconnection handle
con_clsvalue as set by the last call to the MHD_AccessHandlerCallback, should be our struct Socks5Request *
toereason for request termination (ignored)

Definition at line 2270 of file gnunet-gns-proxy.c.

References Socks5Request::curl, curl_download_prepare(), curl_failure_response, curl_multi, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_log, Socks5Request::header_head, Socks5Request::header_tail, Socks5Request::headers, Socks5Request::io_len, Socks5Request::rbuf_len, Socks5Request::response, SOCKS5_SOCKET_WITH_MHD, Socks5Request::state, Socks5Request::url, and Socks5Request::wbuf_len.

Referenced by lookup_ssl_httpd(), and run().

2274 {
2275  struct Socks5Request *s5r = *con_cls;
2276 
2277  if (NULL == s5r)
2278  return;
2279  if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe)
2281  "MHD encountered error handling request: %d\n",
2282  toe);
2283  if (NULL != s5r->curl)
2284  {
2286  "Removing cURL handle (MHD interaction complete)\n");
2287  curl_multi_remove_handle (curl_multi,
2288  s5r->curl);
2289  curl_slist_free_all (s5r->headers);
2290  s5r->headers = NULL;
2291  curl_easy_reset (s5r->curl);
2292  s5r->rbuf_len = 0;
2293  s5r->wbuf_len = 0;
2294  s5r->io_len = 0;
2296  }
2297  if ( (NULL != s5r->response) &&
2298  (curl_failure_response != s5r->response) )
2299  MHD_destroy_response (s5r->response);
2300  for (struct HttpResponseHeader *header = s5r->header_head;
2301  NULL != header;
2302  header = s5r->header_head)
2303  {
2305  s5r->header_tail,
2306  header);
2307  GNUNET_free (header->type);
2308  GNUNET_free (header->value);
2309  GNUNET_free (header);
2310  }
2312  "Finished request for %s\n",
2313  s5r->url);
2314  GNUNET_free (s5r->url);
2316  s5r->url = NULL;
2317  s5r->response = NULL;
2318  *con_cls = NULL;
2319 }
struct HttpResponseHeader * header_head
Headers from response.
Socket has been passed to MHD, do not close it anymore.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static struct MHD_Response * curl_failure_response
Response we return on cURL failures.
size_t io_len
Number of bytes already in the IO buffer.
size_t rbuf_len
Number of bytes already in read buffer.
A header list.
struct HttpResponseHeader * header_tail
Headers from response.
struct curl_slist * headers
HTTP request headers for the curl request.
enum SocksPhase state
The socks state.
struct MHD_Response * response
MHD response object for this request.
static void curl_download_prepare()
Ask cURL for the select() sets and schedule cURL operations.
#define GNUNET_log(kind,...)
char * url
The URL to fetch.
A structure for socks requests.
static CURLM * curl_multi
The cURL multi handle.
#define GNUNET_free(ptr)
Wrapper around free.
CURL * curl
Handle to cURL.
size_t wbuf_len
Number of bytes already in write buffer.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mhd_connection_cb()

static void mhd_connection_cb ( void *  cls,
struct MHD_Connection *  connection,
void **  con_cls,
enum MHD_ConnectionNotificationCode  cnc 
)
static

Function called when MHD connection is opened or closed.

Parameters
clsNULL
connectionconnection handle
con_clsvalue as set by the last call to the MHD_AccessHandlerCallback, should be our struct Socks5Request *
toeconnection notification type

Definition at line 2332 of file gnunet-gns-proxy.c.

References cleanup_s5r(), curl_download_prepare(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_NETWORK_get_fd(), GNUNET_NO, Socks5Request::next, Socks5Request::sock, and Socks5Request::ssl_checked.

Referenced by lookup_ssl_httpd(), and run().

2336 {
2337  struct Socks5Request *s5r;
2338  const union MHD_ConnectionInfo *ci;
2339  int sock;
2340 
2341  switch (cnc)
2342  {
2343  case MHD_CONNECTION_NOTIFY_STARTED:
2344  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection started...\n");
2345  ci = MHD_get_connection_info (connection,
2346  MHD_CONNECTION_INFO_CONNECTION_FD);
2347  if (NULL == ci)
2348  {
2349  GNUNET_break (0);
2350  return;
2351  }
2352  sock = ci->connect_fd;
2353  for (s5r = s5r_head; NULL != s5r; s5r = s5r->next)
2354  {
2355  if (GNUNET_NETWORK_get_fd (s5r->sock) == sock)
2356  {
2358  "Context set...\n");
2359  s5r->ssl_checked = GNUNET_NO;
2360  *con_cls = s5r;
2361  break;
2362  }
2363  }
2364  break;
2365  case MHD_CONNECTION_NOTIFY_CLOSED:
2367  "Connection closed... cleaning up\n");
2368  s5r = *con_cls;
2369  if (NULL == s5r)
2370  {
2372  "Connection stale!\n");
2373  return;
2374  }
2375  cleanup_s5r (s5r);
2377  *con_cls = NULL;
2378  break;
2379  default:
2380  GNUNET_break (0);
2381  }
2382 }
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1268
struct GNUNET_NETWORK_Handle * sock
The client socket.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
int ssl_checked
X.509 Certificate status.
struct Socks5Request * next
DLL.
static struct Socks5Request * s5r_head
DLL of active socks requests.
static void cleanup_s5r(struct Socks5Request *s5r)
Clean up s5r handles.
static void curl_download_prepare()
Ask cURL for the select() sets and schedule cURL operations.
#define GNUNET_log(kind,...)
A structure for socks requests.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mhd_log_callback()

static void* mhd_log_callback ( void *  cls,
const char *  url,
struct MHD_Connection *  connection 
)
static

Function called when MHD first processes an incoming connection.

Gives us the respective URI information.

We use this to associate the struct MHD_Connection with our internal struct Socks5Request data structure (by checking for matching sockets).

Parameters
clsthe HTTP server handle (a struct MhdHttpList)
urlthe URL that is being requested
connectionMHD connection object for the request
Returns
the struct Socks5Request that this connection is for

Definition at line 2398 of file gnunet-gns-proxy.c.

References GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_SCHEDULER_cancel(), GNUNET_strdup, SOCKS5_SOCKET_WITH_MHD, Socks5Request::state, Socks5Request::timeout_task, and Socks5Request::url.

Referenced by lookup_ssl_httpd(), and run().

2401 {
2402  struct Socks5Request *s5r;
2403  const union MHD_ConnectionInfo *ci;
2404 
2405  ci = MHD_get_connection_info (connection,
2406  MHD_CONNECTION_INFO_SOCKET_CONTEXT);
2407  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing %s\n", url);
2408  if (NULL == ci)
2409  {
2410  GNUNET_break (0);
2411  return NULL;
2412  }
2413  s5r = ci->socket_context;
2414  if (NULL != s5r->url)
2415  {
2416  GNUNET_break (0);
2417  return NULL;
2418  }
2419  s5r->url = GNUNET_strdup (url);
2420  if (NULL != s5r->timeout_task)
2421  {
2423  s5r->timeout_task = NULL;
2424  }
2426  return s5r;
2427 }
Socket has been passed to MHD, do not close it anymore.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
enum SocksPhase state
The socks state.
struct GNUNET_SCHEDULER_Task * timeout_task
Timeout task.
#define GNUNET_log(kind,...)
char * url
The URL to fetch.
A structure for socks requests.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
Here is the call graph for this function:
Here is the caller graph for this function:

◆ kill_httpd()

static void kill_httpd ( struct MhdHttpList hd)
static

Kill the given MHD daemon.

Parameters
hddaemon to stop

Definition at line 2436 of file gnunet-gns-proxy.c.

References MhdHttpList::daemon, MhdHttpList::domain, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_free_non_null, GNUNET_SCHEDULER_cancel(), MhdHttpList::httpd_task, and MhdHttpList::proxy_cert.

Referenced by do_shutdown(), kill_httpd_task(), and schedule_httpd().

2437 {
2440  hd);
2442  MHD_stop_daemon (hd->daemon);
2443  if (NULL != hd->httpd_task)
2444  {
2446  hd->httpd_task = NULL;
2447  }
2449  if (hd == httpd)
2450  httpd = NULL;
2451  GNUNET_free (hd);
2452 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
char * domain
the domain name to server (only important for TLS)
static struct MhdHttpList * mhd_httpd_tail
DLL for http/https daemons.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
static struct MhdHttpList * httpd
Daemon for HTTP (we have one per X.509 certificate, and then one for all HTTP connections; this is th...
struct MHD_Daemon * daemon
The daemon handle.
static struct MhdHttpList * mhd_httpd_head
DLL for http/https daemons.
struct ProxyGNSCertificate * proxy_cert
Optional proxy certificate used.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_SCHEDULER_Task * httpd_task
The task ID.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
Here is the call graph for this function:
Here is the caller graph for this function:

◆ kill_httpd_task()

static void kill_httpd_task ( void *  cls)
static

Task run whenever HTTP server is idle for too long.

Kill it.

Parameters
clsthe struct MhdHttpList *

Definition at line 2461 of file gnunet-gns-proxy.c.

References do_httpd(), MhdHttpList::httpd_task, and kill_httpd().

Referenced by schedule_httpd().

2462 {
2463  struct MhdHttpList *hd = cls;
2464 
2465  hd->httpd_task = NULL;
2466  kill_httpd (hd);
2467 }
A structure for all running Httpds.
static void kill_httpd(struct MhdHttpList *hd)
Kill the given MHD daemon.
struct GNUNET_SCHEDULER_Task * httpd_task
The task ID.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_httpd()

static void do_httpd ( void *  cls)
static

Task run whenever HTTP server operations are pending.

Parameters
clsthe struct MhdHttpList * of the daemon that is being run
clsthe struct MhdHttpList of the daemon that is being run

Definition at line 2565 of file gnunet-gns-proxy.c.

References MhdHttpList::daemon, MhdHttpList::httpd_task, and schedule_httpd().

Referenced by kill_httpd_task(), run_mhd_now(), and schedule_httpd().

2566 {
2567  struct MhdHttpList *hd = cls;
2568 
2569  hd->httpd_task = NULL;
2570  MHD_run (hd->daemon);
2571  schedule_httpd (hd);
2572 }
static void schedule_httpd(struct MhdHttpList *hd)
Schedule MHD.
struct MHD_Daemon * daemon
The daemon handle.
A structure for all running Httpds.
struct GNUNET_SCHEDULER_Task * httpd_task
The task ID.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ schedule_httpd()

static void schedule_httpd ( struct MhdHttpList hd)
static

Schedule MHD.

This function should be called initially when an MHD is first getting its client socket, and will then automatically always be called later whenever there is work to be done.

Parameters
hdthe daemon to schedule

Definition at line 2487 of file gnunet-gns-proxy.c.

References MhdHttpList::daemon, do_httpd(), GNUNET_NETWORK_fdset_copy_native(), GNUNET_NETWORK_fdset_create(), GNUNET_NETWORK_fdset_destroy(), GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_add_select(), GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_TIME_UNIT_FOREVER_REL, MhdHttpList::httpd_task, kill_httpd(), kill_httpd_task(), MHD_CACHE_TIMEOUT, GNUNET_TIME_Relative::rel_value_us, and timeout.

Referenced by do_httpd(), and setup_data_transfer().

2488 {
2489  fd_set rs;
2490  fd_set ws;
2491  fd_set es;
2492  struct GNUNET_NETWORK_FDSet *wrs;
2493  struct GNUNET_NETWORK_FDSet *wws;
2494  int max;
2495  int haveto;
2496  MHD_UNSIGNED_LONG_LONG timeout;
2497  struct GNUNET_TIME_Relative tv;
2498 
2499  FD_ZERO (&rs);
2500  FD_ZERO (&ws);
2501  FD_ZERO (&es);
2502  max = -1;
2503  if (MHD_YES !=
2504  MHD_get_fdset (hd->daemon,
2505  &rs,
2506  &ws,
2507  &es,
2508  &max))
2509  {
2510  kill_httpd (hd);
2511  return;
2512  }
2513  haveto = MHD_get_timeout (hd->daemon,
2514  &timeout);
2515  if (MHD_YES == haveto)
2516  tv.rel_value_us = (uint64_t) timeout * 1000LL;
2517  else
2519  if (-1 != max)
2520  {
2521  wrs = GNUNET_NETWORK_fdset_create ();
2522  wws = GNUNET_NETWORK_fdset_create ();
2523  GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
2524  GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
2525  }
2526  else
2527  {
2528  wrs = NULL;
2529  wws = NULL;
2530  }
2531  if (NULL != hd->httpd_task)
2532  {
2534  hd->httpd_task = NULL;
2535  }
2536  if ( (MHD_YES != haveto) &&
2537  (-1 == max) &&
2538  (hd != httpd) )
2539  {
2540  /* daemon is idle, kill after timeout */
2542  &kill_httpd_task,
2543  hd);
2544  }
2545  else
2546  {
2547  hd->httpd_task =
2549  tv, wrs, wws,
2550  &do_httpd, hd);
2551  }
2552  if (NULL != wrs)
2554  if (NULL != wws)
2556 }
#define MHD_CACHE_TIMEOUT
After how long do we clean up unused MHD TLS instances?
static void kill_httpd_task(void *cls)
Task run whenever HTTP server is idle for too long.
void GNUNET_NETWORK_fdset_copy_native(struct GNUNET_NETWORK_FDSet *to, const fd_set *from, int nfds)
Copy a native fd set into the GNUnet representation.
Definition: network.c:1308
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1554
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1246
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1538
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
static struct MhdHttpList * httpd
Daemon for HTTP (we have one per X.509 certificate, and then one for all HTTP connections; this is th...
collection of IO descriptors
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition: scheduler.c:1829
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct MHD_Daemon * daemon
The daemon handle.
static void kill_httpd(struct MhdHttpList *hd)
Kill the given MHD daemon.
static void do_httpd(void *cls)
Task run whenever HTTP server operations are pending.
Run with the default priority (normal P2P operations).
struct GNUNET_SCHEDULER_Task * httpd_task
The task ID.
Time for relative time used by GNUnet, in microseconds.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_file()

static void* load_file ( const char *  filename,
unsigned int *  size 
)
static

Read file in filename.

Parameters
filenamefile to read
sizepointer where filesize is stored
Returns
NULL on error

Definition at line 2598 of file gnunet-gns-proxy.c.

References GNUNET_DISK_file_size(), GNUNET_DISK_fn_read(), GNUNET_free, GNUNET_malloc, GNUNET_OK, GNUNET_YES, and MAX_PEM_SIZE.

Referenced by load_cert_from_file(), and load_key_from_file().

2600 {
2601  void *buffer;
2602  uint64_t fsize;
2603 
2604  if (GNUNET_OK !=
2606  &fsize,
2607  GNUNET_YES,
2608  GNUNET_YES))
2609  return NULL;
2610  if (fsize > MAX_PEM_SIZE)
2611  return NULL;
2612  *size = (unsigned int) fsize;
2613  buffer = GNUNET_malloc (*size);
2614  if (fsize !=
2616  buffer,
2617  (size_t) fsize))
2618  {
2619  GNUNET_free (buffer);
2620  return NULL;
2621  }
2622  return buffer;
2623 }
#define MAX_PEM_SIZE
Largest allowed size for a PEM certificate.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static char * filename
static unsigned int size
Size of the "table".
Definition: peer.c:67
int GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:289
#define GNUNET_YES
Definition: gnunet_common.h:80
#define GNUNET_malloc(size)
Wrapper around malloc.
ssize_t GNUNET_DISK_fn_read(const char *fn, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:1019
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_key_from_file()

static int load_key_from_file ( gnutls_x509_privkey_t  key,
const char *  keyfile 
)
static

Load PEM key from file.

Parameters
keywhere to store the data
keyfilepath to the PEM file
Returns
GNUNET_OK on success

Definition at line 2634 of file gnunet-gns-proxy.c.

References _, GNUNET_ERROR_TYPE_ERROR, GNUNET_free_non_null, GNUNET_log, GNUNET_OK, GNUNET_SYSERR, load_file(), and ret.

Referenced by run().

2636 {
2637  gnutls_datum_t key_data;
2638  int ret;
2639 
2640  key_data.data = load_file (keyfile,
2641  &key_data.size);
2642  if (NULL == key_data.data)
2643  return GNUNET_SYSERR;
2644  ret = gnutls_x509_privkey_import (key, &key_data,
2645  GNUTLS_X509_FMT_PEM);
2646  if (GNUTLS_E_SUCCESS != ret)
2647  {
2649  _("Unable to import private key from file `%s'\n"),
2650  keyfile);
2651  }
2652  GNUNET_free_non_null (key_data.data);
2653  return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK;
2654 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
static void * load_file(const char *filename, unsigned int *size)
Read file in filename.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
#define GNUNET_log(kind,...)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_cert_from_file()

static int load_cert_from_file ( gnutls_x509_crt_t  crt,
const char *  certfile 
)
static

Load cert from file.

Parameters
crtstruct to store data in
certfilepath to pem file
Returns
GNUNET_OK on success

Definition at line 2665 of file gnunet-gns-proxy.c.

References _, GNUNET_ERROR_TYPE_ERROR, GNUNET_free_non_null, GNUNET_log, GNUNET_OK, GNUNET_SYSERR, load_file(), and ret.

Referenced by run().

2667 {
2668  gnutls_datum_t cert_data;
2669  int ret;
2670 
2671  cert_data.data = load_file (certfile,
2672  &cert_data.size);
2673  if (NULL == cert_data.data)
2674  return GNUNET_SYSERR;
2675  ret = gnutls_x509_crt_import (crt,
2676  &cert_data,
2677  GNUTLS_X509_FMT_PEM);
2678  if (GNUTLS_E_SUCCESS != ret)
2679  {
2681  _("Unable to import certificate from `%s'\n"),
2682  certfile);
2683  }
2684  GNUNET_free_non_null (cert_data.data);
2685  return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK;
2686 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
static void * load_file(const char *filename, unsigned int *size)
Read file in filename.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
#define GNUNET_log(kind,...)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ generate_gns_certificate()

static struct ProxyGNSCertificate* generate_gns_certificate ( const char *  name)
static

Generate new certificate for specific name.

Parameters
namethe subject name to generate a cert for
Returns
a struct holding the PEM data, NULL on error

Definition at line 2696 of file gnunet-gns-proxy.c.

References ProxyCA::cert, ProxyGNSCertificate::cert, etime, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_new, ProxyCA::key, ProxyGNSCertificate::key, proxy_ca, and request.

Referenced by lookup_ssl_httpd().

2697 {
2698  unsigned int serial;
2699  size_t key_buf_size;
2700  size_t cert_buf_size;
2701  gnutls_x509_crt_t request;
2702  time_t etime;
2703  struct tm *tm_data;
2704  struct ProxyGNSCertificate *pgc;
2705 
2707  "Generating x.509 certificate for `%s'\n",
2708  name);
2709  GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_init (&request));
2710  GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_set_key (request, proxy_ca.key));
2711  pgc = GNUNET_new (struct ProxyGNSCertificate);
2712  gnutls_x509_crt_set_dn_by_oid (request,
2713  GNUTLS_OID_X520_COUNTRY_NAME,
2714  0,
2715  "ZZ",
2716  strlen ("ZZ"));
2717  gnutls_x509_crt_set_dn_by_oid (request,
2718  GNUTLS_OID_X520_ORGANIZATION_NAME,
2719  0,
2720  "GNU Name System",
2721  strlen ("GNU Name System"));
2722  gnutls_x509_crt_set_dn_by_oid (request,
2723  GNUTLS_OID_X520_COMMON_NAME,
2724  0,
2725  name,
2726  strlen (name));
2727  gnutls_x509_crt_set_subject_alternative_name (request,
2728  GNUTLS_SAN_DNSNAME,
2729  name);
2730  GNUNET_break (GNUTLS_E_SUCCESS ==
2731  gnutls_x509_crt_set_version (request,
2732  3));
2733  gnutls_rnd (GNUTLS_RND_NONCE,
2734  &serial,
2735  sizeof (serial));
2736  gnutls_x509_crt_set_serial (request,
2737  &serial,
2738  sizeof (serial));
2739  etime = time (NULL);
2740  tm_data = localtime (&etime);
2741  tm_data->tm_hour--;
2742  etime = mktime(tm_data);
2743  gnutls_x509_crt_set_activation_time (request,
2744  etime);
2745  tm_data->tm_year++;
2746  etime = mktime (tm_data);
2747  gnutls_x509_crt_set_expiration_time (request,
2748  etime);
2749  gnutls_x509_crt_sign2 (request,
2750  proxy_ca.cert,
2751  proxy_ca.key,
2752  GNUTLS_DIG_SHA512,
2753  0);
2754  key_buf_size = sizeof (pgc->key);
2755  cert_buf_size = sizeof (pgc->cert);
2756  gnutls_x509_crt_export (request,
2757  GNUTLS_X509_FMT_PEM,
2758  pgc->cert,
2759  &cert_buf_size);
2760  gnutls_x509_privkey_export (proxy_ca.key,
2761  GNUTLS_X509_FMT_PEM,
2762  pgc->key,
2763  &key_buf_size);
2764  gnutls_x509_crt_deinit (request);
2765  return pgc;
2766 }
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:41
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static struct ProxyCA proxy_ca
The CA for X.509 certificate generation.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static uint64_t etime
Expiration string converted to numeric value.
const char * name
char key[(10 *1024)]
The private key as PEM.
char cert[(10 *1024)]
The certificate as PEM.
gnutls_x509_privkey_t key
The private key.
#define GNUNET_log(kind,...)
gnutls_x509_crt_t cert
The certificate.
Structure for GNS certificates.
Here is the caller graph for this function:

◆ mhd_error_log_callback()

static void mhd_error_log_callback ( void *  cls,
const char *  fm,
va_list  ap 
)
static

Function called by MHD with errors, suppresses them all.

Parameters
clsclosure
fmformat string (printf()-style)
aparguments to fm

Definition at line 2777 of file gnunet-gns-proxy.c.

Referenced by lookup_ssl_httpd().

2780 {
2781  /* do nothing */
2782 }
Here is the caller graph for this function:

◆ lookup_ssl_httpd()

static struct MhdHttpList* lookup_ssl_httpd ( const char *  domain)
static

Lookup (or create) an TLS MHD instance for a particular domain.

Parameters
domainthe domain the TLS daemon has to serve
Returns
NULL on error

Definition at line 2792 of file gnunet-gns-proxy.c.

References ProxyGNSCertificate::cert, create_response(), MhdHttpList::daemon, MhdHttpList::domain, generate_gns_certificate(), GNUNET_break, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_new, GNUNET_strdup, GNUNET_YES, MhdHttpList::is_ssl, ProxyGNSCertificate::key, mhd_completed_cb(), mhd_connection_cb(), mhd_error_log_callback(), mhd_log_callback(), MhdHttpList::next, and MhdHttpList::proxy_cert.

Referenced by setup_data_transfer().

2793 {
2794  struct MhdHttpList *hd;
2795  struct ProxyGNSCertificate *pgc;
2796 
2797  if (NULL == domain)
2798  {
2799  GNUNET_break (0);
2800  return NULL;
2801  }
2802  for (hd = mhd_httpd_head; NULL != hd; hd = hd->next)
2803  if ( (NULL != hd->domain) &&
2804  (0 == strcmp (hd->domain, domain)) )
2805  return hd;
2807  "Starting fresh MHD HTTPS instance for domain `%s'\n",
2808  domain);
2809  pgc = generate_gns_certificate (domain);
2810  hd = GNUNET_new (struct MhdHttpList);
2811  hd->is_ssl = GNUNET_YES;
2812  hd->domain = GNUNET_strdup (domain);
2813  hd->proxy_cert = pgc;
2814  hd->daemon = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SSL | MHD_USE_NO_LISTEN_SOCKET | MHD_ALLOW_SUSPEND_RESUME,
2815  0,
2816  NULL, NULL,
2817  &create_response, hd,
2818  MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16,
2819  MHD_OPTION_NOTIFY_COMPLETED, &mhd_completed_cb, NULL,
2820  MHD_OPTION_NOTIFY_CONNECTION, &mhd_connection_cb, NULL,
2821  MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, NULL,
2822  MHD_OPTION_EXTERNAL_LOGGER, &mhd_error_log_callback, NULL,
2823  MHD_OPTION_HTTPS_MEM_KEY, pgc->key,
2824  MHD_OPTION_HTTPS_MEM_CERT, pgc->cert,
2825  MHD_OPTION_END);
2826  if (NULL == hd->daemon)
2827  {
2828  GNUNET_free (pgc);
2829  GNUNET_free (hd);
2830  return NULL;
2831  }
2834  hd);
2835  return hd;
2836 }
static void mhd_connection_cb(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_ConnectionNotificationCode cnc)
Function called when MHD connection is opened or closed.
char * domain
the domain name to server (only important for TLS)
static struct MhdHttpList * mhd_httpd_tail
DLL for http/https daemons.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
static void mhd_error_log_callback(void *cls, const char *fm, va_list ap)
Function called by MHD with errors, suppresses them all.
static void * mhd_log_callback(void *cls, const char *url, struct MHD_Connection *connection)
Function called when MHD first processes an incoming connection.
struct MhdHttpList * next
DLL for httpds.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static void mhd_completed_cb(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
Function called when MHD decides that we are done with a request.
int is_ssl
is this an ssl daemon?
struct MHD_Daemon * daemon
The daemon handle.
char key[(10 *1024)]
The private key as PEM.
char cert[(10 *1024)]
The certificate as PEM.
A structure for all running Httpds.
static struct MhdHttpList * mhd_httpd_head
DLL for http/https daemons.
struct ProxyGNSCertificate * proxy_cert
Optional proxy certificate used.
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:80
static struct ProxyGNSCertificate * generate_gns_certificate(const char *name)
Generate new certificate for specific name.
static int create_response(void *cls, struct MHD_Connection *con, const char *url, const char *meth, const char *ver, const char *upload_data, size_t *upload_data_size, void **con_cls)
Main MHD callback for handling requests.
Structure for GNS certificates.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ timeout_s5r_handshake()

static void timeout_s5r_handshake ( void *  cls)
static

Task run when a Socks5Request somehow fails to be associated with an MHD connection (i.e.

because the client never speaks HTTP after the SOCKS5 handshake). Clean up.

Parameters
clsthe struct Socks5Request *

Definition at line 2847 of file gnunet-gns-proxy.c.

References cleanup_s5r(), and Socks5Request::timeout_task.

Referenced by setup_data_transfer().

2848 {
2849  struct Socks5Request *s5r = cls;
2850 
2851  s5r->timeout_task = NULL;
2852  cleanup_s5r (s5r);
2853 }
struct GNUNET_SCHEDULER_Task * timeout_task
Timeout task.
static void cleanup_s5r(struct Socks5Request *s5r)
Clean up s5r handles.
A structure for socks requests.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_data_transfer()

static void setup_data_transfer ( struct Socks5Request s5r)
static

We're done with the Socks5 protocol, now we need to pass the connection data through to the final destination, either direct (if the protocol might not be HTTP), or via MHD (if the port looks like it should be HTTP).

Parameters
s5rsocks request that has reached the final stage

Definition at line 2865 of file gnunet-gns-proxy.c.

References _, cleanup_s5r(), MhdHttpList::daemon, Socks5Request::domain, GNUNET_asprintf(), GNUNET_assert, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_free_non_null, GNUNET_log, GNUNET_NETWORK_get_addr(), GNUNET_NETWORK_get_addrlen(), GNUNET_NETWORK_get_fd(), GNUNET_SCHEDULER_add_delayed(), GNUNET_YES, Socks5Request::hd, HTTP_HANDSHAKE_TIMEOUT, httpd, Socks5Request::is_tls, len, lookup_ssl_httpd(), schedule_httpd(), Socks5Request::sock, SOCKS5_SOCKET_WITH_MHD, Socks5Request::state, timeout_s5r_handshake(), and Socks5Request::timeout_task.

Referenced by do_write().

2866 {
2867  struct MhdHttpList *hd;
2868  int fd;
2869  const struct sockaddr *addr;
2870  socklen_t len;
2871  char *domain;
2872 
2873  if (GNUNET_YES == s5r->is_tls)
2874  {
2875  GNUNET_asprintf (&domain,
2876  "%s",
2877  s5r->domain);
2878  hd = lookup_ssl_httpd (domain);
2879  if (NULL == hd)
2880  {
2882  _("Failed to start HTTPS server for `%s'\n"),
2883  s5r->domain);
2884  cleanup_s5r (s5r);
2885  GNUNET_free (domain);
2886  return;
2887  }
2888  } else {
2889  domain = NULL;
2890  GNUNET_assert (NULL != httpd);
2891  hd = httpd;
2892  }
2893  fd = GNUNET_NETWORK_get_fd (s5r->sock);
2894  addr = GNUNET_NETWORK_get_addr (s5r->sock);
2895  len = GNUNET_NETWORK_get_addrlen (s5r->sock);
2897  if (MHD_YES !=
2898  MHD_add_connection (hd->daemon,
2899  fd,
2900  addr,
2901  len))
2902  {
2904  _("Failed to pass client to MHD\n"));
2905  cleanup_s5r (s5r);
2906  GNUNET_free_non_null (domain);
2907  return;
2908  }
2909  s5r->hd = hd;
2910  schedule_httpd (hd);
2913  s5r);
2914  GNUNET_free_non_null (domain);
2915 }
Socket has been passed to MHD, do not close it anymore.
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1268
struct sockaddr * GNUNET_NETWORK_get_addr(const struct GNUNET_NETWORK_Handle *desc)
Return the sockaddr for this network handle.
Definition: network.c:1281
socklen_t GNUNET_NETWORK_get_addrlen(const struct GNUNET_NETWORK_Handle *desc)
Return sockaddr length for this network handle.
Definition: network.c:1294
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_NETWORK_Handle * sock
The client socket.
#define HTTP_HANDSHAKE_TIMEOUT
After how long do we clean up Socks5 handles that failed to show any activity with their respective M...
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1246
static struct MhdHttpList * httpd
Daemon for HTTP (we have one per X.509 certificate, and then one for all HTTP connections; this is th...
enum SocksPhase state
The socks state.
struct MhdHttpList * hd
MHD HTTP instance handling this request, NULL for none.
char * domain
the domain name to server (only important for TLS)
static void schedule_httpd(struct MhdHttpList *hd)
Schedule MHD.
struct MHD_Daemon * daemon
The daemon handle.
static struct MhdHttpList * lookup_ssl_httpd(const char *domain)
Lookup (or create) an TLS MHD instance for a particular domain.
struct GNUNET_SCHEDULER_Task * timeout_task
Timeout task.
static void cleanup_s5r(struct Socks5Request *s5r)
Clean up s5r handles.
A structure for all running Httpds.
#define GNUNET_log(kind,...)
int is_tls
This is (probably) a TLS connection.
static void timeout_s5r_handshake(void *cls)
Task run when a Socks5Request somehow fails to be associated with an MHD connection (i...
#define GNUNET_YES
Definition: gnunet_common.h:80
#define GNUNET_free(ptr)
Wrapper around free.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_write()

static void do_write ( void *  cls)
static

Write data from buffer to socks5 client, then continue with state machine.

Parameters
clsthe closure with the struct Socks5Request

Definition at line 2927 of file gnunet-gns-proxy.c.

References cleanup_s5r(), GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_NETWORK_socket_send(), GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_UNIT_FOREVER_REL, len, Socks5Request::rtask, setup_data_transfer(), Socks5Request::sock, SOCKS5_DATA_TRANSFER, SOCKS5_INIT, SOCKS5_REQUEST, SOCKS5_WRITE_THEN_CLEANUP, Socks5Request::state, Socks5Request::wbuf, Socks5Request::wbuf_len, and Socks5Request::wtask.

Referenced by do_s5r_read(), signal_socks_failure(), and signal_socks_success().

2928 {
2929  struct Socks5Request *s5r = cls;
2930  ssize_t len;
2931 
2932  s5r->wtask = NULL;
2933  len = GNUNET_NETWORK_socket_send (s5r->sock,
2934  s5r->wbuf,
2935  s5r->wbuf_len);
2936  if (len <= 0)
2937  {
2938  /* write error: connection closed, shutdown, etc.; just clean up */
2940  "Write Error\n");
2941  cleanup_s5r (s5r);
2942  return;
2943  }
2944  memmove (s5r->wbuf,
2945  &s5r->wbuf[len],
2946  s5r->wbuf_len - len);
2947  s5r->wbuf_len -= len;
2948  if (s5r->wbuf_len > 0)
2949  {
2950  /* not done writing */
2951  s5r->wtask =
2953  s5r->sock,
2954  &do_write, s5r);
2955  return;
2956  }
2957 
2958  /* we're done writing, continue with state machine! */
2959 
2960  switch (s5r->state)
2961  {
2962  case SOCKS5_INIT:
2963  GNUNET_assert (0);
2964  break;
2965  case SOCKS5_REQUEST:
2966  GNUNET_assert (NULL != s5r->rtask);
2967  break;
2968  case SOCKS5_DATA_TRANSFER:
2969  setup_data_transfer (s5r);
2970  return;
2972  cleanup_s5r (s5r);
2973  return;
2974  default:
2975  GNUNET_break (0);
2976  break;
2977  }
2978 }
ssize_t GNUNET_NETWORK_socket_send(const struct GNUNET_NETWORK_Handle *desc, const void *buffer, size_t length)
Send data (always non-blocking).
Definition: network.c:927
We&#39;re waiting to get the client hello.
struct GNUNET_SCHEDULER_Task * wtask
Client socket write task.
static void do_write(void *cls)
Write data from buffer to socks5 client, then continue with state machine.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
We&#39;re waiting to get the initial request.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1548
struct GNUNET_NETWORK_Handle * sock
The client socket.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
char wbuf[(256+32)]
Write buffer.
static void setup_data_transfer(struct Socks5Request *s5r)
We&#39;re done with the Socks5 protocol, now we need to pass the connection data through to the final des...
enum SocksPhase state
The socks state.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_SCHEDULER_Task * rtask
Client socket read task.
Finish writing the write buffer, then clean up.
static void cleanup_s5r(struct Socks5Request *s5r)
Clean up s5r handles.
#define GNUNET_log(kind,...)
We&#39;re in transfer mode.
A structure for socks requests.
size_t wbuf_len
Number of bytes already in write buffer.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ signal_socks_failure()

static void signal_socks_failure ( struct Socks5Request s5r,
enum Socks5StatusCode  sc 
)
static

Return a server response message indicating a failure to the client.

Parameters
s5rrequest to return failure code for
scstatus code to return

Definition at line 2988 of file gnunet-gns-proxy.c.

References do_write(), GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_UNIT_FOREVER_REL, Socks5ServerResponseMessage::reply, sc, Socks5Request::sock, SOCKS5_WRITE_THEN_CLEANUP, SOCKS_VERSION_5, Socks5Request::state, Socks5ServerResponseMessage::version, Socks5Request::wbuf, Socks5Request::wbuf_len, and Socks5Request::wtask.

Referenced by do_s5r_read(), and handle_gns_result().

2990 {
2991  struct Socks5ServerResponseMessage *s_resp;
2992 
2993  s_resp = (struct Socks5ServerResponseMessage *) &s5r->wbuf[s5r->wbuf_len];
2994  memset (s_resp, 0, sizeof (struct Socks5ServerResponseMessage));
2995  s_resp->version = SOCKS_VERSION_5;
2996  s_resp->reply = sc;
2998  if (NULL != s5r->wtask)
2999  s5r->wtask =
3001  s5r->sock,
3002  &do_write, s5r);
3003 }
uint8_t version
Should be SOCKS_VERSION_5.
struct GNUNET_SCHEDULER_Task * wtask
Client socket write task.
static void do_write(void *cls)
Write data from buffer to socks5 client, then continue with state machine.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1548
struct GNUNET_NETWORK_Handle * sock
The client socket.
uint8_t reply
Status code, an enum Socks5StatusCode
char wbuf[(256+32)]
Write buffer.
enum SocksPhase state
The socks state.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
Finish writing the write buffer, then clean up.
static struct GNUNET_FS_SearchContext * sc
Definition: gnunet-search.c:37
Server response to client requests in Socks5 protocol.
#define SOCKS_VERSION_5
Which SOCKS version do we speak?
size_t wbuf_len
Number of bytes already in write buffer.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ signal_socks_success()

static void signal_socks_success ( struct Socks5Request s5r)
static

Return a server response message indicating success.

Parameters
s5rrequest to return success status message for

Definition at line 3012 of file gnunet-gns-proxy.c.

References Socks5ServerResponseMessage::addr_type, do_write(), GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_UNIT_FOREVER_REL, Socks5ServerResponseMessage::reply, Socks5ServerResponseMessage::reserved, Socks5Request::sock, SOCKS5_AT_IPV4, SOCKS5_STATUS_REQUEST_GRANTED, SOCKS_VERSION_5, Socks5ServerResponseMessage::version, Socks5Request::wbuf, Socks5Request::wbuf_len, and Socks5Request::wtask.

Referenced by do_s5r_read(), and handle_gns_result().

3013 {
3014  struct Socks5ServerResponseMessage *s_resp;
3015 
3016  s_resp = (struct Socks5ServerResponseMessage *) &s5r->wbuf[s5r->wbuf_len];
3017  s_resp->version = SOCKS_VERSION_5;
3019  s_resp->reserved = 0;
3020  s_resp->addr_type = SOCKS5_AT_IPV4;
3021  /* zero out IPv4 address and port */
3022  memset (&s_resp[1],
3023  0,
3024  sizeof (struct in_addr) + sizeof (uint16_t));
3025  s5r->wbuf_len += sizeof (struct Socks5ServerResponseMessage) +
3026  sizeof (struct in_addr) + sizeof (uint16_t);
3027  if (NULL == s5r->wtask)
3028  s5r->wtask =
3030  s5r->sock,
3031  &do_write, s5r);
3032 }
uint8_t version
Should be SOCKS_VERSION_5.
uint8_t addr_type
Address type, an enum Socks5AddressType.
struct GNUNET_SCHEDULER_Task * wtask
Client socket write task.
static void do_write(void *cls)
Write data from buffer to socks5 client, then continue with state machine.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1548
struct GNUNET_NETWORK_Handle * sock
The client socket.
IPv4 address.
uint8_t reply
Status code, an enum Socks5StatusCode
char wbuf[(256+32)]
Write buffer.
uint8_t reserved
Always zero.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
Server response to client requests in Socks5 protocol.
#define SOCKS_VERSION_5
Which SOCKS version do we speak?
size_t wbuf_len
Number of bytes already in write buffer.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_gns_result()

static void handle_gns_result ( void *  cls,
int  tld,
uint32_t  rd_count,
const struct GNUNET_GNSRECORD_Data rd 
)
static

Process GNS results for target domain.

Parameters
clsthe struct Socks5Request *
tldGNUNET_YES if this was a GNS TLD.
rd_countnumber of records returned
rdrecord data

Definition at line 3044 of file gnunet-gns-proxy.c.

References Socks5Request::dane_data, Socks5Request::dane_data_len, GNUNET_GNSRECORD_Data::data, GNUNET_GNSRECORD_Data::data_size, Socks5Request::destination_address, disable_v6, Socks5Request::gns_lookup, GNUNET_break, GNUNET_break_op, GNUNET_DNSPARSER_TYPE_A, GNUNET_DNSPARSER_TYPE_AAAA, GNUNET_DNSPARSER_TYPE_TLSA, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free_non_null, GNUNET_GNSRECORD_TYPE_BOX, GNUNET_GNSRECORD_TYPE_LEHO, GNUNET_GNSRECORD_TYPE_VPN, GNUNET_log, GNUNET_memcpy, GNUNET_memdup, GNUNET_NETWORK_test_pf(), GNUNET_NO, GNUNET_OK, GNUNET_strndup, GNUNET_YES, Socks5Request::is_gns, Socks5Request::is_tls, Socks5Request::leho, MAX_DANES, Socks5Request::num_danes, Socks5Request::port, GNUNET_GNSRECORD_BoxRecord::protocol, GNUNET_GNSRECORD_Data::record_type, GNUNET_GNSRECORD_BoxRecord::record_type, GNUNET_GNSRECORD_BoxRecord::service, signal_socks_failure(), signal_socks_success(), SOCKS5_DATA_TRANSFER, SOCKS5_STATUS_GENERAL_FAILURE, and Socks5Request::state.

Referenced by do_s5r_read().

3048 {
3049  struct Socks5Request *s5r = cls;
3050  const struct GNUNET_GNSRECORD_Data *r;
3051  int got_ip;
3052 
3053  s5r->gns_lookup = NULL;
3054  s5r->is_gns = tld;
3055  got_ip = GNUNET_NO;
3056  for (uint32_t i=0;i<rd_count;i++)
3057  {
3058  r = &rd[i];
3059  switch (r->record_type)
3060  {
3062  {
3063  struct sockaddr_in *in;
3064 
3065  if (sizeof (struct in_addr) != r->data_size)
3066  {
3067  GNUNET_break_op (0);
3068  break;
3069  }
3070  if (GNUNET_YES == got_ip)
3071  break;
3072  if (GNUNET_OK !=
3073  GNUNET_NETWORK_test_pf (PF_INET))
3074  break;
3075  got_ip = GNUNET_YES;
3076  in = (struct sockaddr_in *) &s5r->destination_address;
3077  in->sin_family = AF_INET;
3078  GNUNET_memcpy (&in->sin_addr,
3079  r->data,
3080  r->data_size);
3081  in->sin_port = htons (s5r->port);
3082 #if HAVE_SOCKADDR_IN_SIN_LEN
3083  in->sin_len = sizeof (*in);
3084 #endif
3085  }
3086  break;
3088  {
3089  struct sockaddr_in6 *in;
3090 
3091  if (sizeof (struct in6_addr) != r->data_size)
3092  {
3093  GNUNET_break_op (0);
3094  break;
3095  }
3096  if (GNUNET_YES == got_ip)
3097  break;
3098  if (GNUNET_YES == disable_v6)
3099  break;
3100  if (GNUNET_OK !=
3101  GNUNET_NETWORK_test_pf (PF_INET6))
3102  break;
3103  /* FIXME: allow user to disable IPv6 per configuration option... */
3104  got_ip = GNUNET_YES;
3105  in = (struct sockaddr_in6 *) &s5r->destination_address;
3106  in->sin6_family = AF_INET6;
3107  GNUNET_memcpy (&in->sin6_addr,
3108  r->data,
3109  r->data_size);
3110  in->sin6_port = htons (s5r->port);
3111 #if HAVE_SOCKADDR_IN_SIN_LEN
3112  in->sin6_len = sizeof (*in);
3113 #endif
3114  }
3115  break;
3117  GNUNET_break (0); /* should have been translated within GNS */
3118  break;
3120  GNUNET_free_non_null (s5r->leho);
3121  s5r->leho = GNUNET_strndup (r->data,
3122  r->data_size);
3123  break;
3125  {
3126  const struct GNUNET_GNSRECORD_BoxRecord *box;
3127 
3128  if (r->data_size < sizeof (struct GNUNET_GNSRECORD_BoxRecord))
3129  {
3130  GNUNET_break_op (0);
3131  break;
3132  }
3133  box = r->data;
3134  if ( (ntohl (box->record_type) != GNUNET_DNSPARSER_TYPE_TLSA) ||
3135  (ntohs (box->protocol) != IPPROTO_TCP) ||
3136  (ntohs (box->service) != s5r->port) )
3137  break; /* BOX record does not apply */
3138  if (s5r->num_danes >= MAX_DANES)
3139  {
3140  GNUNET_break (0); /* MAX_DANES too small */
3141  break;
3142  }
3143  s5r->is_tls = GNUNET_YES; /* This should be TLS */
3144  s5r->dane_data_len[s5r->num_danes]
3145  = r->data_size - sizeof (struct GNUNET_GNSRECORD_BoxRecord);
3146  s5r->dane_data[s5r->num_danes]
3147  = GNUNET_memdup (&box[1],
3148  s5r->dane_data_len[s5r->num_danes]);
3149  s5r->num_danes++;
3150  break;
3151  }
3152  default:
3153  /* don't care */
3154  break;
3155  }
3156  }
3157  if ( (GNUNET_YES != got_ip) &&
3158  (GNUNET_YES == tld) )
3159  {
3161  "Name resolution failed to yield useful IP address.\n");
3162  signal_socks_failure (s5r,
3164  return;
3165  }
3166  s5r->state = SOCKS5_DATA_TRANSFER;
3167  signal_socks_success (s5r);
3168 }
uint16_t service
Service of the boxed record (aka port number), in NBO.
Record type used to box up SRV and TLSA records.
char * dane_data[32+1]
Payload of the DANE records encountered.
int dane_data_len[32+1]
Number of bytes in dane_data.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define MAX_DANES
Maximum number of DANE records we support per domain name (and port and protocol).
size_t data_size
Number of bytes in data.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_GNSRECORD_TYPE_BOX
Record type for a boxed record (see TLSA/SRV handling in GNS).
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_GNSRECORD_TYPE_VPN
Record type for VPN resolution.
static void signal_socks_failure(struct Socks5Request *s5r, enum Socks5StatusCode sc)
Return a server response message indicating a failure to the client.
#define GNUNET_memcpy(dst, src, n)
const void * data
Binary value stored in the DNS record.
unsigned int num_danes
Number of entries used in dane_data_len and dane_data.
struct GNUNET_GNS_LookupWithTldRequest * gns_lookup
Handle to GNS lookup, during SOCKS5_RESOLVING phase.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
enum SocksPhase state
The socks state.
uint16_t protocol
Protocol of the boxed record (6 = TCP, 17 = UDP, etc.).
uint16_t port
Desired destination port.
struct sockaddr_storage destination_address
Once known, what&#39;s the target address for the connection?
uint32_t record_type
GNS record type of the boxed record.
#define GNUNET_DNSPARSER_TYPE_TLSA
#define GNUNET_GNSRECORD_TYPE_LEHO
Record type for GNS legacy hostnames ("LEHO").
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
int is_gns
Was the hostname resolved via GNS?
uint32_t record_type
Type of the GNS/DNS record.
char * leho
DNS Legacy Host Name as given by GNS, NULL if not given.
#define GNUNET_DNSPARSER_TYPE_AAAA
#define GNUNET_log(kind,...)
int is_tls
This is (probably) a TLS connection.
static void signal_socks_success(struct Socks5Request *s5r)
Return a server response message indicating success.
#define GNUNET_YES
Definition: gnunet_common.h:80
We&#39;re in transfer mode.
A structure for socks requests.
#define GNUNET_DNSPARSER_TYPE_A
int GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition: network.c:84
static int disable_v6
Disable IPv6.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ clear_from_s5r_rbuf()

static void clear_from_s5r_rbuf ( struct Socks5Request s5r,
size_t  len 
)
static

Remove the first len bytes from the beginning of the read buffer.

Parameters
s5rthe handle clear the read buffer for
lennumber of bytes in read buffer to advance

Definition at line 3178 of file gnunet-gns-proxy.c.

References GNUNET_assert, len, Socks5Request::rbuf, and Socks5Request::rbuf_len.

Referenced by do_s5r_read().

3180 {
3181  GNUNET_assert (len <= s5r->rbuf_len);
3182  memmove (s5r->rbuf,
3183  &s5r->rbuf[len],
3184  s5r->rbuf_len - len);
3185  s5r->rbuf_len -= len;
3186 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
char rbuf[(256+32)]
Read buffer.
size_t rbuf_len
Number of bytes already in read buffer.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
Here is the caller graph for this function:

◆ do_s5r_read()

static void do_s5r_read ( void *  cls)
static

Read data from incoming Socks5 connection.

Parameters
clsthe closure with the struct Socks5Request

Definition at line 3195 of file gnunet-gns-proxy.c.

References _, Socks5ClientRequestMessage::addr_type, Socks5ServerHelloMessage::auth_method, cleanup_s5r(), clear_from_s5r_rbuf(), Socks5ClientRequestMessage::command, Socks5Request::destination_address, do_write(), Socks5Request::domain, Socks5Request::gns_lookup, GNUNET_assert, GNUNET_break_op, GNUNET_DNSPARSER_TYPE_A, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_GNS_lookup_with_tld(), GNUNET_log, GNUNET_NETWORK_fdset_isset(), GNUNET_NETWORK_socket_recv(), GNUNET_NO, GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_add_write_net(), GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_get_task_context(), GNUNET_strndup, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, handle_gns_result(), HTTPS_PORT, Socks5Request::is_tls, Socks5ClientHelloMessage::num_auth_methods, Socks5Request::port, port, Socks5Request::rbuf, Socks5Request::rbuf_len, GNUNET_SCHEDULER_TaskContext::read_ready, Socks5Request::rtask, signal_socks_failure(), signal_socks_success(), Socks5Request::sock, SOCKS5_AT_DOMAINNAME, SOCKS5_AT_IPV4, SOCKS5_AT_IPV6, SOCKS5_CMD_TCP_STREAM, SOCKS5_DATA_TRANSFER, SOCKS5_INIT, SOCKS5_REQUEST, SOCKS5_RESOLVING, SOCKS5_STATUS_ADDRESS_TYPE_NOT_SUPPORTED, SOCKS5_STATUS_COMMAND_NOT_SUPPORTED, SOCKS5_STATUS_GENERAL_FAILURE, SOCKS_AUTH_NONE, SOCKS_VERSION_5, Socks5Request::state, tc, Socks5ClientHelloMessage::version, Socks5ServerHelloMessage::version, Socks5Request::wbuf, Socks5Request::wbuf_len, and Socks5Request::wtask.

Referenced by do_accept().

3196 {
3197  struct Socks5Request *s5r = cls;
3198  const struct Socks5ClientHelloMessage *c_hello;
3199  struct Socks5ServerHelloMessage *s_hello;
3200  const struct Socks5ClientRequestMessage *c_req;
3201  ssize_t rlen;
3202  size_t alen;
3203  const struct GNUNET_SCHEDULER_TaskContext *tc;
3204 
3205  s5r->rtask = NULL;
3207  if ( (NULL != tc->read_ready) &&
3209  s5r->sock)) )
3210  {
3211  rlen = GNUNET_NETWORK_socket_recv (s5r->sock,
3212  &s5r->rbuf[s5r->rbuf_len],
3213  sizeof (s5r->rbuf) - s5r->rbuf_len);
3214  if (rlen <= 0)
3215  {
3217  "socks5 client disconnected.\n");
3218  cleanup_s5r (s5r);
3219  return;
3220  }
3221  s5r->rbuf_len += rlen;
3222  }
3224  s5r->sock,
3225  &do_s5r_read, s5r);
3227  "Processing %zu bytes of socks data in state %d\n",
3228  s5r->rbuf_len,
3229  s5r->state);
3230  switch (s5r->state)
3231  {
3232  case SOCKS5_INIT:
3233  c_hello = (const struct Socks5ClientHelloMessage*) &s5r->rbuf;
3234  if ( (s5r->rbuf_len < sizeof (struct Socks5ClientHelloMessage)) ||
3235  (s5r->rbuf_len < sizeof (struct Socks5ClientHelloMessage) + c_hello->num_auth_methods) )
3236  return; /* need more data */
3237  if (SOCKS_VERSION_5 != c_hello->version)
3238  {
3240  _("Unsupported socks version %d\n"),
3241  (int) c_hello->version);
3242  cleanup_s5r (s5r);
3243  return;
3244  }
3245  clear_from_s5r_rbuf (s5r,
3246  sizeof (struct Socks5ClientHelloMessage) + c_hello->num_auth_methods);
3247  GNUNET_assert (0 == s5r->wbuf_len);
3248  s_hello = (struct Socks5ServerHelloMessage *) &s5r->wbuf;
3249  s5r->wbuf_len = sizeof (struct Socks5ServerHelloMessage);
3250  s_hello->version = SOCKS_VERSION_5;
3251  s_hello->auth_method = SOCKS_AUTH_NONE;
3252  GNUNET_assert (NULL == s5r->wtask);
3254  s5r->sock,
3255  &do_write, s5r);
3256  s5r->state = SOCKS5_REQUEST;
3257  return;
3258  case SOCKS5_REQUEST:
3259  c_req = (const struct Socks5ClientRequestMessage *) &s5r->rbuf;
3260  if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage))
3261  return;
3262  switch (c_req->command)
3263  {
3264  case SOCKS5_CMD_TCP_STREAM:
3265  /* handled below */
3266  break;
3267  default:
3269  _("Unsupported socks command %d\n"),
3270  (int) c_req->command);
3271  signal_socks_failure (s5r,
3273  return;
3274  }
3275  switch (c_req->addr_type)
3276  {
3277  case SOCKS5_AT_IPV4:
3278  {
3279  const struct in_addr *v4 = (const struct in_addr *) &c_req[1];
3280  const uint16_t *port = (const uint16_t *) &v4[1];
3281  struct sockaddr_in *in;
3282 
3283  s5r->port = ntohs (*port);
3284  alen = sizeof (struct in_addr);
3285  if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) +
3286  alen + sizeof (uint16_t))
3287  return; /* need more data */
3288  in = (struct sockaddr_in *) &s5r->destination_address;
3289  in->sin_family = AF_INET;
3290  in->sin_addr = *v4;
3291  in->sin_port = *port;
3292 #if HAVE_SOCKADDR_IN_SIN_LEN
3293  in->sin_len = sizeof (*in);
3294 #endif
3295  s5r->state = SOCKS5_DATA_TRANSFER;
3296  }
3297  break;
3298  case SOCKS5_AT_IPV6:
3299  {
3300  const struct in6_addr *v6 = (const struct in6_addr *) &c_req[1];
3301  const uint16_t *port = (const uint16_t *) &v6[1];
3302  struct sockaddr_in6 *in;
3303 
3304  s5r->port = ntohs (*port);
3305  alen = sizeof (struct in6_addr);
3306  if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) +
3307  alen + sizeof (uint16_t))
3308  return; /* need more data */
3309  in = (struct sockaddr_in6 *) &s5r->destination_address;
3310  in->sin6_family = AF_INET6;
3311  in->sin6_addr = *v6;
3312  in->sin6_port = *port;
3313 #if HAVE_SOCKADDR_IN_SIN_LEN
3314  in->sin6_len = sizeof (*in);
3315 #endif
3316  s5r->state = SOCKS5_DATA_TRANSFER;
3317  }
3318  break;
3319  case SOCKS5_AT_DOMAINNAME:
3320  {
3321  const uint8_t *dom_len;
3322  const char *dom_name;
3323  const uint16_t *port;
3324 
3325  dom_len = (const uint8_t *) &c_req[1];
3326  alen = *dom_len + 1;
3327  if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) +
3328  alen + sizeof (uint16_t))
3329  return; /* need more data */
3330  dom_name = (const char *) &dom_len[1];
3331  port = (const uint16_t*) &dom_name[*dom_len];
3332  s5r->domain = GNUNET_strndup (dom_name,
3333  *dom_len);
3335  "Requested connection is to %s:%d\n",
3336  //(HTTPS_PORT == s5r->port) ? "s" : "",
3337  s5r->domain,
3338  ntohs (*port));
3339  s5r->state = SOCKS5_RESOLVING;
3340  s5r->port = ntohs (*port);
3341  s5r->is_tls = (HTTPS_PORT == s5r->port) ? GNUNET_YES : GNUNET_NO;
3343  s5r->domain,
3345  GNUNET_NO /* only cached */,
3347  s5r);
3348  break;
3349  }
3350  default:
3352  _("Unsupported socks address type %d\n"),
3353  (int) c_req->addr_type);
3354  signal_socks_failure (s5r,
3356  return;
3357  }
3358  clear_from_s5r_rbuf (s5r,
3359  sizeof (struct Socks5ClientRequestMessage) +
3360  alen + sizeof (uint16_t));
3361  if (0 != s5r->rbuf_len)
3362  {
3363  /* read more bytes than healthy, why did the client send more!? */
3364  GNUNET_break_op (0);
3365  signal_socks_failure (s5r,
3367  return;
3368  }
3369  if (SOCKS5_DATA_TRANSFER == s5r->state)
3370  {
3371  /* if we are not waiting for GNS resolution, signal success */
3372  signal_socks_success (s5r);
3373  }
3374  /* We are done reading right now */
3376  s5r->rtask = NULL;
3377  return;
3378  case SOCKS5_RESOLVING:
3379  GNUNET_assert (0);
3380  return;
3381  case SOCKS5_DATA_TRANSFER:
3382  GNUNET_assert (0);
3383  return;
3384  default:
3385  GNUNET_assert (0);
3386  return;
3387  }
3388 }
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:746
uint8_t num_auth_methods
How many authentication methods does the client support.
We&#39;re waiting to get the client hello.
Context information passed to each scheduler task.
struct GNUNET_SCHEDULER_Task * wtask
Client socket write task.
ssize_t GNUNET_NETWORK_socket_recv(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length)
Read data from a connected socket (always non-blocking).
Definition: network.c:894
#define HTTPS_PORT
Port for HTTPS.
static void do_write(void *cls)
Write data from buffer to socks5 client, then continue with state machine.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
char rbuf[(256+32)]
Read buffer.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:417
struct GNUNET_GNS_LookupWithTldRequest * GNUNET_GNS_lookup_with_tld(struct GNUNET_GNS_Handle *handle, const char *name, uint32_t type, enum GNUNET_GNS_LocalOptions options, GNUNET_GNS_LookupResultProcessor2 proc, void *proc_cls)
Perform an asynchronous lookup operation on the GNS, determining the zone using the TLD of the given ...
Definition: gns_tld_api.c:242
Server hello in Socks5 protocol.
We&#39;re waiting to get the initial request.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1548
struct GNUNET_NETWORK_Handle * sock
The client socket.
#define GNUNET_NO
Definition: gnunet_common.h:81
IPv4 address.
const struct GNUNET_NETWORK_FDSet * read_ready
Set of file descriptors ready for reading; note that additional bits may be set that were not in the ...
static void do_s5r_read(void *cls)
Read data from incoming Socks5 connection.
#define SOCKS_AUTH_NONE
Flag to set for &#39;no authentication&#39;.
size_t rbuf_len
Number of bytes already in read buffer.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
static uint16_t port
The port the proxy is running on (default 7777)
static void signal_socks_failure(struct Socks5Request *s5r, enum Socks5StatusCode sc)
Return a server response message indicating a failure to the client.
char wbuf[(256+32)]
Write buffer.
Establish TCP/IP stream.
static struct GNUNET_GNS_Handle * gns_handle
Handle to the GNS service.
Client hello in Socks5 protocol.
struct GNUNET_GNS_LookupWithTldRequest * gns_lookup
Handle to GNS lookup, during SOCKS5_RESOLVING phase.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
enum SocksPhase state
The socks state.
uint8_t auth_method
Chosen authentication method, for us always SOCKS_AUTH_NONE, which skips the authentication step...
char * domain
the domain name to server (only important for TLS)
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_SCHEDULER_Task * rtask
Client socket read task.
uint16_t port
Desired destination port.
static void cleanup_s5r(struct Socks5Request *s5r)
Clean up s5r handles.
struct sockaddr_storage destination_address
Once known, what&#39;s the target address for the connection?
uint8_t version
Should be SOCKS_VERSION_5.
uint8_t version
Should be SOCKS_VERSION_5.
Client socks request in Socks5 protocol.
IPv6 address.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_log(kind,...)
int is_tls
This is (probably) a TLS connection.
static void signal_socks_success(struct Socks5Request *s5r)
Return a server response message indicating success.
#define GNUNET_YES
Definition: gnunet_common.h:80
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1478
static void clear_from_s5r_rbuf(struct Socks5Request *s5r, size_t len)
Remove the first len bytes from the beginning of the read buffer.
static void handle_gns_result(void *cls, int tld, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process GNS results for target domain.
We are currently resolving the destination.
We&#39;re in transfer mode.
int GNUNET_NETWORK_fdset_isset(const struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc)
Check whether a socket is part of the fd set.
Definition: network.c:1181
A structure for socks requests.
#define SOCKS_VERSION_5
Which SOCKS version do we speak?
#define GNUNET_DNSPARSER_TYPE_A
uint8_t command
Command code, we only uspport SOCKS5_CMD_TCP_STREAM.
size_t wbuf_len
Number of bytes already in write buffer.
uint8_t addr_type
Address type, an enum Socks5AddressType.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_accept()

static void do_accept ( void *  cls)
static

Accept new incoming connections.

Parameters
clsthe closure with the lsock4 or lsock6
tcthe scheduler context

Definition at line 3398 of file gnunet-gns-proxy.c.

References do_s5r_read(), GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_socket_accept(), GNUNET_new, GNUNET_SCHEDULER_add_read_net(), GNUNET_TIME_UNIT_FOREVER_REL, Socks5Request::rtask, Socks5Request::sock, SOCKS5_INIT, and Socks5Request::state.

Referenced by run().

3399 {
3400  struct GNUNET_NETWORK_Handle *lsock = cls;
3401  struct GNUNET_NETWORK_Handle *s;
3402  struct Socks5Request *s5r;
3403 
3404  GNUNET_assert (NULL != lsock);
3405  if (lsock == lsock4)
3407  lsock,
3408  &do_accept,
3409  lsock);
3410  else if (lsock == lsock6)
3412  lsock,
3413  &do_accept,
3414  lsock);
3415  else
3416  GNUNET_assert (0);
3417  s = GNUNET_NETWORK_socket_accept (lsock,
3418  NULL,
3419  NULL);
3420  if (NULL == s)
3421  {
3423  "accept");
3424  return;
3425  }
3427  "Got an inbound connection, waiting for data\n");
3428  s5r = GNUNET_new (struct Socks5Request);
3430  s5r_tail,
3431  s5r);
3432  s5r->sock = s;
3433  s5r->state = SOCKS5_INIT;
3435  s5r->sock,
3436  &do_s5r_read,
3437  s5r);
3438 }
static struct Socks5Request * s5r_tail
DLL of active socks requests.
static struct GNUNET_SCHEDULER_Task * ltask4
The listen task ID for IPv4.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
We&#39;re waiting to get the client hello.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_NETWORK_Handle * sock
The client socket.
static struct GNUNET_SCHEDULER_Task * ltask6
The listen task ID for IPv6.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static void do_s5r_read(void *cls)
Read data from incoming Socks5 connection.
static struct GNUNET_NETWORK_Handle * lsock6
The listen socket of the proxy for IPv6.
static struct GNUNET_NETWORK_Handle * lsock4
The listen socket of the proxy for IPv4.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_accept(const struct GNUNET_NETWORK_Handle *desc, struct sockaddr *address, socklen_t *address_len)
Accept a new connection on a socket.
Definition: network.c:468
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
static void do_accept(void *cls)
Accept new incoming connections.
enum SocksPhase state
The socks state.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_SCHEDULER_Task * rtask
Client socket read task.
static struct Socks5Request * s5r_head
DLL of active socks requests.
#define GNUNET_log(kind,...)
handle to a socket
Definition: network.c:46
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1478
A structure for socks requests.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_shutdown()

static void do_shutdown ( void *  cls)
static

Task run on shutdown.

Parameters
clsclosure

Definition at line 3450 of file gnunet-gns-proxy.c.

References ProxyCA::cert, cleanup_s5r(), curl_multi, GNUNET_ERROR_TYPE_INFO, GNUNET_GNS_disconnect(), GNUNET_log, GNUNET_NETWORK_socket_close(), GNUNET_NO, GNUNET_SCHEDULER_cancel(), ProxyCA::key, kill_httpd(), Socks5Request::next, and proxy_ca.

Referenced by run().

3451 {
3453  "Shutting down...\n");
3454  /* MHD requires resuming before destroying the daemons */
3455  for (struct Socks5Request *s5r = s5r_head;
3456  NULL != s5r;
3457  s5r = s5r->next)
3458  {
3459  if (s5r->suspended)
3460  {
3461  s5r->suspended = GNUNET_NO;
3462  MHD_resume_connection (s5r->con);
3463  }
3464  }
3465  while (NULL != mhd_httpd_head)
3467  while (NULL != s5r_head)
3469  if (NULL != lsock4)
3470  {
3472  lsock4 = NULL;
3473  }
3474  if (NULL != lsock6)
3475  {
3477  lsock6 = NULL;
3478  }
3479  if (NULL != curl_multi)
3480  {
3481  curl_multi_cleanup (curl_multi);
3482  curl_multi = NULL;
3483  }
3484  if (NULL != gns_handle)
3485  {
3487  gns_handle = NULL;
3488  }
3489  if (NULL != curl_download_task)
3490  {
3492  curl_download_task = NULL;
3493  }
3494  if (NULL != ltask4)
3495  {
3497  ltask4 = NULL;
3498  }
3499  if (NULL != ltask6)
3500  {
3502  ltask6 = NULL;
3503  }
3504  gnutls_x509_crt_deinit (proxy_ca.cert);
3505  gnutls_x509_privkey_deinit (proxy_ca.key);
3506  gnutls_global_deinit ();
3507 }
static struct GNUNET_SCHEDULER_Task * ltask4
The listen task ID for IPv4.
static struct GNUNET_SCHEDULER_Task * ltask6
The listen task ID for IPv6.
#define GNUNET_NO
Definition: gnunet_common.h:81
static struct ProxyCA proxy_ca
The CA for X.509 certificate generation.
static struct GNUNET_NETWORK_Handle * lsock6
The listen socket of the proxy for IPv6.
static struct GNUNET_NETWORK_Handle * lsock4
The listen socket of the proxy for IPv4.
static struct GNUNET_GNS_Handle * gns_handle
Handle to the GNS service.
void GNUNET_GNS_disconnect(struct GNUNET_GNS_Handle *handle)
Shutdown connection with the GNS service.
Definition: gns_api.c:285
struct Socks5Request * next
DLL.
static struct Socks5Request * s5r_head
DLL of active socks requests.
static void cleanup_s5r(struct Socks5Request *s5r)
Clean up s5r handles.
static struct GNUNET_SCHEDULER_Task * curl_download_task
The cURL download task (curl multi API).
static void kill_httpd(struct MhdHttpList *hd)
Kill the given MHD daemon.
gnutls_x509_privkey_t key
The private key.
static struct MhdHttpList * mhd_httpd_head
DLL for http/https daemons.
#define GNUNET_log(kind,...)
gnutls_x509_crt_t cert
The certificate.
A structure for socks requests.
static CURLM * curl_multi
The cURL multi handle.
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:604
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bind_v4()

static struct GNUNET_NETWORK_Handle* bind_v4 ( )
static

Create an IPv4 listen socket bound to our port.

Returns
NULL on error

Definition at line 3516 of file gnunet-gns-proxy.c.

References address, GNUNET_NETWORK_socket_bind(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_OK, ls, and port.

Referenced by run().

3517 {
3518  struct GNUNET_NETWORK_Handle *ls;
3519  struct sockaddr_in sa4;
3520  int eno;
3521 
3522  memset (&sa4, 0, sizeof (sa4));
3523  sa4.sin_family = AF_INET;
3524  sa4.sin_port = htons (port);
3525  sa4.sin_addr.s_addr = address;
3526 #if HAVE_SOCKADDR_IN_SIN_LEN
3527  sa4.sin_len = sizeof (sa4);
3528 #endif
3529  ls = GNUNET_NETWORK_socket_create (AF_INET,
3530  SOCK_STREAM,
3531  0);
3532  if (NULL == ls)
3533  return NULL;
3534  if (GNUNET_OK !=
3536  (const struct sockaddr *) &sa4,
3537  sizeof (sa4)))
3538  {
3539  eno = errno;
3541  errno = eno;
3542  return NULL;
3543  }
3544  return ls;
3545 }
int GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition: network.c:522
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static in_addr_t address
The address to bind to.
static uint16_t port
The port the proxy is running on (default 7777)
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition: gnunet-nat.c:85
handle to a socket
Definition: network.c:46
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:604
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:1037
Here is the call graph for this function:
Here is the caller graph for this function:

◆ bind_v6()

static struct GNUNET_NETWORK_Handle* bind_v6 ( )
static

Create an IPv6 listen socket bound to our port.

Returns
NULL on error

Definition at line 3554 of file gnunet-gns-proxy.c.

References address6, GNUNET_NETWORK_socket_bind(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_OK, ls, and port.

Referenced by run().

3555 {
3556  struct GNUNET_NETWORK_Handle *ls;
3557  struct sockaddr_in6 sa6;
3558  int eno;
3559 
3560  memset (&sa6, 0, sizeof (sa6));
3561  sa6.sin6_family = AF_INET6;
3562  sa6.sin6_port = htons (port);
3563  sa6.sin6_addr = address6;
3564 #if HAVE_SOCKADDR_IN_SIN_LEN
3565  sa6.sin6_len = sizeof (sa6);
3566 #endif
3567  ls = GNUNET_NETWORK_socket_create (AF_INET6,
3568  SOCK_STREAM,
3569  0);
3570  if (NULL == ls)
3571  return NULL;
3572  if (GNUNET_OK !=
3574  (const struct sockaddr *) &sa6,
3575  sizeof (sa6)))
3576  {
3577  eno = errno;
3579  errno = eno;
3580  return NULL;
3581  }
3582  return ls;
3583 }
int GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition: network.c:522
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static uint16_t port
The port the proxy is running on (default 7777)
static struct in6_addr address6
The IPv6 address to bind to.
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition: gnunet-nat.c:85
handle to a socket
Definition: network.c:46
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:604
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:1037
Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

static void run ( void *  cls,
char *const *  args,
const char *  cfgfile,
const struct GNUNET_CONFIGURATION_Handle c 
)
static

Main function that will be run.

Parameters
clsclosure
argsremaining command-line arguments
cfgfilename of the configuration file used (for saving, can be NULL!)
cconfiguration

Definition at line 3595 of file gnunet-gns-proxy.c.

References _, address, address6, bind_v4(), bind_v6(), cafile_opt, ProxyCA::cert, create_response(), curl_multi, MhdHttpList::daemon, do_accept(), do_shutdown(), GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_free_non_null, GNUNET_GNS_connect(), GNUNET_log, GNUNET_log_config_missing(), GNUNET_log_strerror, GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_listen(), GNUNET_new, GNUNET_OK, GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), GNUNET_TIME_UNIT_FOREVER_REL, inet_pton(), ProxyCA::key, load_cert_from_file(), load_key_from_file(), mhd_completed_cb(), mhd_connection_cb(), mhd_log_callback(), port, and proxy_ca.

Referenced by main().

3599 {
3600  char* cafile_cfg = NULL;
3601  char* cafile;
3602  char* addr_str;
3603  struct MhdHttpList *hd;
3604 
3605  cfg = c;
3606 
3607  /* Get address to bind to */
3609  "BIND_TO",
3610  &addr_str))
3611  {
3612  //No address specified
3614  "Don't know what to bind to...\n");
3615  GNUNET_free (addr_str);
3617  return;
3618  }
3619  if (1 != inet_pton (AF_INET, addr_str, &address))
3620  {
3622  "Unable to parse address %s\n",
3623  addr_str);
3624  GNUNET_free (addr_str);
3626  return;
3627  }
3628  GNUNET_free (addr_str);
3629  /* Get address to bind to */
3631  "BIND_TO6",
3632  &addr_str))
3633  {
3634  //No address specified
3636  "Don't know what to bind6 to...\n");
3637  GNUNET_free (addr_str);
3639  return;
3640  }
3641  if (1 != inet_pton (AF_INET6, addr_str, &address6))
3642  {
3644  "Unable to parse IPv6 address %s\n",
3645  addr_str);
3646  GNUNET_free (addr_str);
3648  return;
3649  }
3650  GNUNET_free (addr_str);
3651 
3652  if (NULL == (curl_multi = curl_multi_init ()))
3653  {
3655  "Failed to create cURL multi handle!\n");
3656  return;
3657  }
3658  cafile = cafile_opt;
3659  if (NULL == cafile)
3660  {
3661  if (GNUNET_OK !=
3663  "gns-proxy",
3664  "PROXY_CACERT",
3665  &cafile_cfg))
3666  {
3668  "gns-proxy",
3669  "PROXY_CACERT");
3670  return;
3671  }
3672  cafile = cafile_cfg;
3673  }
3675  "Using `%s' as CA\n",
3676  cafile);
3677 
3678  gnutls_global_init ();
3679  gnutls_x509_crt_init (&proxy_ca.cert);
3680  gnutls_x509_privkey_init (&proxy_ca.key);
3681 
3682  if ( (GNUNET_OK !=
3684  cafile)) ||
3685  (GNUNET_OK !=
3687  cafile)) )
3688  {
3690  _("Failed to load X.509 key and certificate from `%s'\n"),
3691  cafile);
3692  gnutls_x509_crt_deinit (proxy_ca.cert);
3693  gnutls_x509_privkey_deinit (proxy_ca.key);
3694  gnutls_global_deinit ();
3695  GNUNET_free_non_null (cafile_cfg);
3696  return;
3697  }
3698  GNUNET_free_non_null (cafile_cfg);
3699  if (NULL == (gns_handle = GNUNET_GNS_connect (cfg)))
3700  {
3702  "Unable to connect to GNS!\n");
3703  gnutls_x509_crt_deinit (proxy_ca.cert);
3704  gnutls_x509_privkey_deinit (proxy_ca.key);
3705  gnutls_global_deinit ();
3706  return;
3707  }
3709  NULL);
3710 
3711  /* Open listen socket for socks proxy */
3712  lsock6 = bind_v6 ();
3713  if (NULL == lsock6)
3714  {
3716  "bind");
3717  }
3718  else
3719  {
3720  if (GNUNET_OK !=
3722  5))
3723  {
3725  "listen");
3727  lsock6 = NULL;
3728  }
3729  else
3730  {
3732  lsock6,
3733  &do_accept,
3734  lsock6);
3735  }
3736  }
3737  lsock4 = bind_v4 ();
3738  if (NULL == lsock4)
3739  {
3741  "bind");
3742  }
3743  else
3744  {
3745  if (GNUNET_OK !=
3747  5))
3748  {
3750  "listen");
3752  lsock4 = NULL;
3753  }
3754  else
3755  {
3757  lsock4,
3758  &do_accept,
3759  lsock4);
3760  }
3761  }
3762  if ( (NULL == lsock4) &&
3763  (NULL == lsock6) )
3764  {
3766  return;
3767  }
3768  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
3769  {
3771  "cURL global init failed!\n");
3773  return;
3774  }
3776  "Proxy listens on port %u\n",
3777  (unsigned int) port);
3778 
3779  /* start MHD daemon for HTTP */
3780  hd = GNUNET_new (struct MhdHttpList);
3781  hd->daemon = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_NO_LISTEN_SOCKET | MHD_ALLOW_SUSPEND_RESUME,
3782  0,
3783  NULL, NULL,
3784  &create_response, hd,
3785  MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16,
3786  MHD_OPTION_NOTIFY_COMPLETED, &mhd_completed_cb, NULL,
3787  MHD_OPTION_NOTIFY_CONNECTION, &mhd_connection_cb, NULL,
3788  MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, NULL,
3789  MHD_OPTION_END);
3790  if (NULL == hd->daemon)
3791  {
3792  GNUNET_free (hd);
3794  return;
3795  }
3796  httpd = hd;
3799  hd);
3800 }