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

HTTP(S) proxy that rewrites URIs and fakes certificates 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 "gnunet_mhd_compat.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
 After how long do we clean up unused MHD TLS instances? More...
 
#define HTTP_HANDSHAKE_TIMEOUT
 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 MHD_RESULT 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 (e.g. 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 certificates 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 51 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 57 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 63 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 69 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 76 of file gnunet-gns-proxy.c.

Referenced by signal_socks_failure().

◆ HTTP_PORT

#define HTTP_PORT   80

Port for plaintext HTTP.

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

◆ HTTPS_PORT

#define HTTPS_PORT   443

Port for HTTPS.

Definition at line 86 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 91 of file gnunet-gns-proxy.c.

Referenced by load_file().

◆ MHD_CACHE_TIMEOUT

#define MHD_CACHE_TIMEOUT
Value:
#define GNUNET_TIME_UNIT_MINUTES
One minute.
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:311

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

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

Referenced by schedule_httpd().

◆ HTTP_HANDSHAKE_TIMEOUT

#define HTTP_HANDSHAKE_TIMEOUT
Value:
#define GNUNET_TIME_UNIT_SECONDS
One second.
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:311

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:178
#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 114 of file gnunet-gns-proxy.c.

◆ SOCKS_VERSION_5

#define SOCKS_VERSION_5   0x05

Which SOCKS version do we speak?

Definition at line 128 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 133 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 139 of file gnunet-gns-proxy.c.

140 {
145 
150 
155 };
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 161 of file gnunet-gns-proxy.c.

162 {
166  SOCKS5_AT_IPV4 = 1,
167 
172 
176  SOCKS5_AT_IPV6 = 4
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 384 of file gnunet-gns-proxy.c.

385 {
389  SOCKS5_INIT,
390 
395 
400 
405 
410 
415 
420 
425 
430 
435 };
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 2590 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().

2591 {
2592  if (NULL != hd->httpd_task)
2595  hd);
2596 }
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:1296
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:972
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 774 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_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().

775 {
777  "Cleaning up socks request\n");
778  if (NULL != s5r->curl)
779  {
781  "Cleaning up cURL handle\n");
782  curl_multi_remove_handle (curl_multi,
783  s5r->curl);
784  curl_easy_cleanup (s5r->curl);
785  s5r->curl = NULL;
786  }
787  if (s5r->suspended)
788  {
789  s5r->suspended = GNUNET_NO;
790  MHD_resume_connection (s5r->con);
791  }
792  curl_slist_free_all (s5r->headers);
793  if (NULL != s5r->hosts)
794  {
795  curl_slist_free_all (s5r->hosts);
796  }
797  if ((NULL != s5r->response) &&
799  {
800  MHD_destroy_response (s5r->response);
801  s5r->response = NULL;
802  }
803  if (NULL != s5r->rtask)
804  {
806  s5r->rtask = NULL;
807  }
808  if (NULL != s5r->timeout_task)
809  {
811  s5r->timeout_task = NULL;
812  }
813  if (NULL != s5r->wtask)
814  {
816  s5r->wtask = NULL;
817  }
818  if (NULL != s5r->gns_lookup)
819  {
821  s5r->gns_lookup = NULL;
822  }
823  if (NULL != s5r->sock)
824  {
825  if (SOCKS5_SOCKET_WITH_MHD <= s5r->state)
827  else
829  s5r->sock = NULL;
830  }
832  s5r_tail,
833  s5r);
834  GNUNET_free (s5r->domain);
835  GNUNET_free (s5r->leho);
836  GNUNET_free (s5r->url);
837  for (unsigned int i = 0; i < s5r->num_danes; i++)
838  GNUNET_free (s5r->dane_data[i]);
839  GNUNET_free (s5r);
840 }
#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:332
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.
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:622
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:560
#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:972
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 1570 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, GNUNET_TIME_UNIT_MILLISECONDS, and max.

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

1571 {
1572  CURLMcode mret;
1573  fd_set rs;
1574  fd_set ws;
1575  fd_set es;
1576  int max;
1577  struct GNUNET_NETWORK_FDSet *grs;
1578  struct GNUNET_NETWORK_FDSet *gws;
1579  long to;
1580  struct GNUNET_TIME_Relative rtime;
1581 
1583  "Scheduling CURL interaction\n");
1584  if (NULL != curl_download_task)
1585  {
1587  curl_download_task = NULL;
1588  }
1589  max = -1;
1590  FD_ZERO (&rs);
1591  FD_ZERO (&ws);
1592  FD_ZERO (&es);
1593  if (CURLM_OK != (mret = curl_multi_fdset (curl_multi,
1594  &rs,
1595  &ws,
1596  &es,
1597  &max)))
1598  {
1600  "%s failed at %s:%d: `%s'\n",
1601  "curl_multi_fdset", __FILE__, __LINE__,
1602  curl_multi_strerror (mret));
1603  return;
1604  }
1605  to = -1;
1606  GNUNET_break (CURLM_OK ==
1607  curl_multi_timeout (curl_multi,
1608  &to));
1609  if (-1 == to)
1611  else
1613  to);
1614  if (-1 != max)
1615  {
1616  grs = GNUNET_NETWORK_fdset_create ();
1617  gws = GNUNET_NETWORK_fdset_create ();
1619  &rs,
1620  max + 1);
1622  &ws,
1623  max + 1);
1626  rtime,
1627  grs,
1628  gws,
1630  curl_multi);
1633  }
1634  else
1635  {
1638  curl_multi);
1639  }
1640 }
#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:1117
#define max(x, y)
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1263
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:1269
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1247
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:1841
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:311
#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:972
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 861 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().

865 {
866  struct Socks5Request *s5r = cls;
867  size_t bytes_to_copy;
868 
869  if ((SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state) ||
871  {
872  /* we're still not done with the upload, do not yet
873  start the download, the IO buffer is still full
874  with upload data. */
876  "Pausing MHD download %s%s, not yet ready for download\n",
877  s5r->domain,
878  s5r->url);
879  return 0; /* not yet ready for data download */
880  }
881  bytes_to_copy = GNUNET_MIN (max,
882  s5r->io_len);
883  if ((0 == bytes_to_copy) &&
885  {
887  "Pausing MHD download %s%s, no data available\n",
888  s5r->domain,
889  s5r->url);
890  if (NULL != s5r->curl)
891  {
893  "Continuing CURL interaction for %s%s\n",
894  s5r->domain,
895  s5r->url);
896  if (GNUNET_YES == s5r->curl_paused)
897  {
898  s5r->curl_paused = GNUNET_NO;
899  curl_easy_pause (s5r->curl,
900  CURLPAUSE_CONT);
901  }
903  }
904  if (GNUNET_NO == s5r->suspended)
905  {
906  MHD_suspend_connection (s5r->con);
907  s5r->suspended = GNUNET_YES;
908  }
909  return 0; /* more data later */
910  }
911  if ((0 == bytes_to_copy) &&
913  {
915  "Completed MHD download %s%s\n",
916  s5r->domain,
917  s5r->url);
918  return MHD_CONTENT_READER_END_OF_STREAM;
919  }
921  "Writing %llu/%llu bytes to %s%s\n",
922  (unsigned long long) bytes_to_copy,
923  (unsigned long long) s5r->io_len,
924  s5r->domain,
925  s5r->url);
927  s5r->io_buf,
928  bytes_to_copy);
929  memmove (s5r->io_buf,
930  &s5r->io_buf[bytes_to_copy],
931  s5r->io_len - bytes_to_copy);
932  s5r->io_len -= bytes_to_copy;
933  if ((NULL != s5r->curl) &&
934  (GNUNET_YES == s5r->curl_paused))
935  {
937  "Continuing CURL interaction for %s%s\n",
938  s5r->domain,
939  s5r->url);
940  s5r->curl_paused = GNUNET_NO;
941  curl_easy_pause (s5r->curl,
942  CURLPAUSE_CONT);
943  }
944  return bytes_to_copy;
945 }
struct MHD_Connection * con
MHD connection for this request.
int curl_paused
Did we pause CURL processing?
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
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 max(x, y)
int suspended
Did we suspend MHD processing?
enum SocksPhase state
The socks state.
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:93
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).
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 957 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().

958 {
959  unsigned int cert_list_size;
960  const gnutls_datum_t *chainp;
961  const struct curl_tlssessioninfo *tlsinfo;
962  char certdn[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 3];
963  size_t size;
964  gnutls_x509_crt_t x509_cert;
965  int rc;
966  const char *name;
967 
968  s5r->ssl_checked = GNUNET_YES;
970  "Checking X.509 certificate\n");
971  if (CURLE_OK !=
972  curl_easy_getinfo (s5r->curl,
973  CURLINFO_TLS_SESSION,
974  &tlsinfo))
975  return GNUNET_SYSERR;
976  if (CURLSSLBACKEND_GNUTLS != tlsinfo->backend)
977  {
979  _ ("Unsupported CURL TLS backend %d\n"),
980  tlsinfo->backend);
981  return GNUNET_SYSERR;
982  }
983  chainp = gnutls_certificate_get_peers (tlsinfo->internals,
984  &cert_list_size);
985  if ((! chainp) ||
986  (0 == cert_list_size))
987  return GNUNET_SYSERR;
988 
989  size = sizeof(certdn);
990  /* initialize an X.509 certificate structure. */
991  gnutls_x509_crt_init (&x509_cert);
992  gnutls_x509_crt_import (x509_cert,
993  chainp,
994  GNUTLS_X509_FMT_DER);
995 
996  if (0 != (rc = gnutls_x509_crt_get_dn_by_oid (x509_cert,
997  GNUTLS_OID_X520_COMMON_NAME,
998  0, /* the first and only one */
999  0 /* no DER encoding */,
1000  certdn,
1001  &size)))
1002  {
1004  _ ("Failed to fetch CN from cert: %s\n"),
1005  gnutls_strerror (rc));
1006  gnutls_x509_crt_deinit (x509_cert);
1007  return GNUNET_SYSERR;
1008  }
1009  /* check for TLSA/DANE records */
1010 #if HAVE_GNUTLS_DANE
1011  if (0 != s5r->num_danes)
1012  {
1013  dane_state_t dane_state;
1014  dane_query_t dane_query;
1015  unsigned int verify;
1016 
1017  /* FIXME: add flags to gnutls to NOT read UNBOUND_ROOT_KEY_FILE here! */
1018  if (0 != (rc = dane_state_init (&dane_state,
1019 #ifdef DANE_F_IGNORE_DNSSEC
1020  DANE_F_IGNORE_DNSSEC |
1021 #endif
1022  DANE_F_IGNORE_LOCAL_RESOLVER)))
1023  {
1025  _ ("Failed to initialize DANE: %s\n"),
1026  dane_strerror (rc));
1027  gnutls_x509_crt_deinit (x509_cert);
1028  return GNUNET_SYSERR;
1029  }
1030  s5r->dane_data[s5r->num_danes] = NULL;
1031  s5r->dane_data_len[s5r->num_danes] = 0;
1032  if (0 != (rc = dane_raw_tlsa (dane_state,
1033  &dane_query,
1034  s5r->dane_data,
1035  s5r->dane_data_len,
1036  GNUNET_YES,
1037  GNUNET_NO)))
1038  {
1040  _ ("Failed to parse DANE record: %s\n"),
1041  dane_strerror (rc));
1042  dane_state_deinit (dane_state);
1043  gnutls_x509_crt_deinit (x509_cert);
1044  return GNUNET_SYSERR;
1045  }
1046  if (0 != (rc = dane_verify_crt_raw (dane_state,
1047  chainp,
1048  cert_list_size,
1049  gnutls_certificate_type_get (
1050  tlsinfo->internals),
1051  dane_query,
1052  0, 0,
1053  &verify)))
1054  {
1056  _ ("Failed to verify TLS connection using DANE: %s\n"),
1057  dane_strerror (rc));
1058  dane_query_deinit (dane_query);
1059  dane_state_deinit (dane_state);
1060  gnutls_x509_crt_deinit (x509_cert);
1061  return GNUNET_SYSERR;
1062  }
1063  if (0 != verify)
1064  {
1066  _ (
1067  "Failed DANE verification failed with GnuTLS verify status code: %u\n"),
1068  verify);
1069  dane_query_deinit (dane_query);
1070  dane_state_deinit (dane_state);
1071  gnutls_x509_crt_deinit (x509_cert);
1072  return GNUNET_SYSERR;
1073  }
1074  dane_query_deinit (dane_query);
1075  dane_state_deinit (dane_state);
1076  /* success! */
1077  }
1078  else
1079 #endif
1080  {
1081  /* try LEHO or ordinary domain name X509 verification */
1082  name = s5r->domain;
1083  if (NULL != s5r->leho)
1084  name = s5r->leho;
1085  if (NULL != name)
1086  {
1087  if (0 == (rc = gnutls_x509_crt_check_hostname (x509_cert,
1088  name)))
1089  {
1091  _ (
1092  "TLS certificate subject name (%s) does not match `%s': %d\n"),
1093  certdn,
1094  name,
1095  rc);
1096  gnutls_x509_crt_deinit (x509_cert);
1097  return GNUNET_SYSERR;
1098  }
1099  }
1100  else
1101  {
1102  /* we did not even have the domain name!? */
1103  GNUNET_break (0);
1104  return GNUNET_SYSERR;
1105  }
1106  }
1107  gnutls_x509_crt_deinit (x509_cert);
1108  return GNUNET_OK;
1109 }
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_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:178
#define GNUNET_DNSPARSER_MAX_NAME_LENGTH
Maximum length of a name in DNS.
int ssl_checked
X.509 Certificate status.
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)
static unsigned int size
Size of the "table".
Definition: peer.c:67
char * leho
DNS Legacy Host Name as given by GNS, NULL if not given.
const char * name
#define GNUNET_log(kind,...)
static int verify
Verify mode.
Definition: gnunet-abd.c:127
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 1125 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_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().

1129 {
1130  struct Socks5Request *s5r = cls;
1131  struct HttpResponseHeader *header;
1132  size_t bytes = size * nmemb;
1133  char *ndup;
1134  const char *hdr_type;
1135  const char *cookie_domain;
1136  char *hdr_val;
1137  char *new_cookie_hdr;
1138  char *new_location;
1139  size_t offset;
1140  size_t delta_cdomain;
1141  int domain_matched;
1142  char *tok;
1143 
1145  "Receiving HTTP response header from CURL\n");
1146  /* first, check TLS certificate */
1147  if ((GNUNET_YES != s5r->ssl_checked) &&
1148  (GNUNET_YES == s5r->is_tls))
1149  // (HTTPS_PORT == s5r->port))
1150  {
1151  if (GNUNET_OK != check_ssl_certificate (s5r))
1152  return 0;
1153  }
1154  ndup = GNUNET_strndup (buffer,
1155  bytes);
1156  hdr_type = strtok (ndup,
1157  ":");
1158  if (NULL == hdr_type)
1159  {
1160  GNUNET_free (ndup);
1161  return bytes;
1162  }
1163  hdr_val = strtok (NULL,
1164  "");
1165  if (NULL == hdr_val)
1166  {
1167  GNUNET_free (ndup);
1168  return bytes;
1169  }
1170  if (' ' == *hdr_val)
1171  hdr_val++;
1172 
1173  /* custom logic for certain header types */
1174  new_cookie_hdr = NULL;
1175  if ((NULL != s5r->leho) &&
1176  (0 == strcasecmp (hdr_type,
1177  MHD_HTTP_HEADER_SET_COOKIE)))
1178 
1179  {
1180  new_cookie_hdr = GNUNET_malloc (strlen (hdr_val)
1181  + strlen (s5r->domain) + 1);
1182  offset = 0;
1183  domain_matched = GNUNET_NO; /* make sure we match domain at most once */
1184  for (tok = strtok (hdr_val, ";"); NULL != tok; tok = strtok (NULL, ";"))
1185  {
1186  if ((0 == strncasecmp (tok,
1187  " domain",
1188  strlen (" domain"))) &&
1189  (GNUNET_NO == domain_matched))
1190  {
1191  domain_matched = GNUNET_YES;
1192  cookie_domain = tok + strlen (" domain") + 1;
1193  if (strlen (cookie_domain) < strlen (s5r->leho))
1194  {
1195  delta_cdomain = strlen (s5r->leho) - strlen (cookie_domain);
1196  if (0 == strcasecmp (cookie_domain,
1197  s5r->leho + delta_cdomain))
1198  {
1199  offset += sprintf (new_cookie_hdr + offset,
1200  " domain=%s;",
1201  s5r->domain);
1202  continue;
1203  }
1204  }
1205  else if (0 == strcmp (cookie_domain,
1206  s5r->leho))
1207  {
1208  offset += sprintf (new_cookie_hdr + offset,
1209  " domain=%s;",
1210  s5r->domain);
1211  continue;
1212  }
1213  else if (('.' == cookie_domain[0]) &&
1214  (0 == strcmp (&cookie_domain[1],
1215  s5r->leho)))
1216  {
1217  offset += sprintf (new_cookie_hdr + offset,
1218  " domain=.%s;",
1219  s5r->domain);
1220  continue;
1221  }
1223  _ ("Cookie domain `%s' supplied by server is invalid\n"),
1224  tok);
1225  }
1226  GNUNET_memcpy (new_cookie_hdr + offset,
1227  tok,
1228  strlen (tok));
1229  offset += strlen (tok);
1230  new_cookie_hdr[offset++] = ';';
1231  }
1232  hdr_val = new_cookie_hdr;
1233  }
1234 
1235  new_location = NULL;
1236  if (0 == strcasecmp (MHD_HTTP_HEADER_TRANSFER_ENCODING,
1237  hdr_type))
1238  {
1239  /* Ignore transfer encoding, set automatically by MHD if required */
1240  goto cleanup;
1241  }
1242  if ((0 == strcasecmp (MHD_HTTP_HEADER_LOCATION,
1243  hdr_type)))
1244  {
1245  char *leho_host;
1246 
1247  GNUNET_asprintf (&leho_host,
1248  (GNUNET_YES != s5r->is_tls) // (HTTPS_PORT != s5r->port)
1249  ? "http://%s"
1250  : "https://%s",
1251  s5r->leho);
1252  if (0 == strncmp (leho_host,
1253  hdr_val,
1254  strlen (leho_host)))
1255  {
1256  GNUNET_asprintf (&new_location,
1257  "%s%s%s",
1258  (GNUNET_YES != s5r->is_tls) // (HTTPS_PORT != s5r->port)
1259  ? "http://"
1260  : "https://",
1261  s5r->domain,
1262  hdr_val + strlen (leho_host));
1263  hdr_val = new_location;
1264  }
1265  GNUNET_free (leho_host);
1266  }
1267  if (0 == strcasecmp (MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
1268  hdr_type))
1269  {
1270  char *leho_host;
1271 
1272  GNUNET_asprintf (&leho_host,
1273  (GNUNET_YES != s5r->is_tls) // (HTTPS_PORT != s5r->port)
1274  ? "http://%s"
1275  : "https://%s",
1276  s5r->leho);
1277  if (0 == strncmp (leho_host,
1278  hdr_val,
1279  strlen (leho_host)))
1280  {
1281  GNUNET_asprintf (&new_location,
1282  "%s%s",
1283  (GNUNET_YES != s5r->is_tls) // (HTTPS_PORT != s5r->port)
1284  ? "http://"
1285  : "https://",
1286  s5r->domain);
1287  hdr_val = new_location;
1288  }
1289  GNUNET_free (leho_host);
1290  }
1291 
1292  /* MHD does not allow certain characters in values, remove those */
1293  if (NULL != (tok = strchr (hdr_val, '\n')))
1294  *tok = '\0';
1295  if (NULL != (tok = strchr (hdr_val, '\r')))
1296  *tok = '\0';
1297  if (NULL != (tok = strchr (hdr_val, '\t')))
1298  *tok = '\0';
1299  if (0 != strlen (hdr_val)) /* Rely in MHD to set those */
1300  {
1302  "Adding header %s: %s to MHD response\n",
1303  hdr_type,
1304  hdr_val);
1305  header = GNUNET_new (struct HttpResponseHeader);
1306  header->type = GNUNET_strdup (hdr_type);
1307  header->value = GNUNET_strdup (hdr_val);
1309  s5r->header_tail,
1310  header);
1311  }
1312 cleanup:
1313  GNUNET_free (ndup);
1314  GNUNET_free (new_cookie_hdr);
1315  GNUNET_free (new_location);
1316  return bytes;
1317 }
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_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#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:178
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.
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.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
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.
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 1329 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().

1330 {
1331  long resp_code;
1332  double content_length;
1333 
1334  if (NULL != s5r->response)
1335  {
1337  "Response already set!\n");
1338  return GNUNET_SYSERR;
1339  }
1340 
1341  GNUNET_break (CURLE_OK ==
1342  curl_easy_getinfo (s5r->curl,
1343  CURLINFO_RESPONSE_CODE,
1344  &resp_code));
1345  GNUNET_break (CURLE_OK ==
1346  curl_easy_getinfo (s5r->curl,
1347  CURLINFO_CONTENT_LENGTH_DOWNLOAD,
1348  &content_length));
1350  "Creating MHD response with code %d and size %d for %s%s\n",
1351  (int) resp_code,
1352  (int) content_length,
1353  s5r->domain,
1354  s5r->url);
1355  s5r->response_code = resp_code;
1356  s5r->response = MHD_create_response_from_callback ((-1 == content_length)
1357  ? MHD_SIZE_UNKNOWN
1358  : content_length,
1359  IO_BUFFERSIZE,
1360  &mhd_content_cb,
1361  s5r,
1362  NULL);
1363  for (struct HttpResponseHeader *header = s5r->header_head;
1364  NULL != header;
1365  header = header->next)
1366  {
1367  if (0 == strcasecmp (header->type,
1368  MHD_HTTP_HEADER_CONTENT_LENGTH))
1369  continue; /* MHD won't let us mess with those, for good reason */
1370  if ((0 == strcasecmp (header->type,
1371  MHD_HTTP_HEADER_TRANSFER_ENCODING)) &&
1372  ((0 == strcasecmp (header->value,
1373  "identity")) ||
1374  (0 == strcasecmp (header->value,
1375  "chunked"))))
1376  continue; /* MHD won't let us mess with those, for good reason */
1377  if (MHD_YES !=
1378  MHD_add_response_header (s5r->response,
1379  header->type,
1380  header->value))
1381  {
1382  GNUNET_break (0);
1384  "Failed to add header `%s:%s'\n",
1385  header->type,
1386  header->value);
1387  }
1388  }
1389  /* force connection to be closed after each request, as we
1390  do not support HTTP pipelining (yet, FIXME!) */
1391  /*GNUNET_break (MHD_YES ==
1392  MHD_add_response_header (s5r->response,
1393  MHD_HTTP_HEADER_CONNECTION,
1394  "close"));*/
1395  MHD_resume_connection (s5r->con);
1396  s5r->suspended = GNUNET_NO;
1397  return GNUNET_OK;
1398 }
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_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.
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 1412 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().

1416 {
1417  struct Socks5Request *s5r = ctx;
1418  size_t total = size * nmemb;
1419 
1421  "Receiving %ux%u bytes for `%s%s' from cURL to download\n",
1422  (unsigned int) size,
1423  (unsigned int) nmemb,
1424  s5r->domain,
1425  s5r->url);
1426  if (NULL == s5r->response)
1429  if ((SOCKS5_SOCKET_UPLOAD_DONE == s5r->state) &&
1430  (0 == s5r->io_len))
1431  {
1433  "Previous upload finished... starting DOWNLOAD.\n");
1435  }
1436  if ((SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state) ||
1437  (SOCKS5_SOCKET_UPLOAD_DONE == s5r->state))
1438  {
1439  /* we're still not done with the upload, do not yet
1440  start the download, the IO buffer is still full
1441  with upload data. */
1443  "Pausing CURL download `%s%s', waiting for UPLOAD to finish\n",
1444  s5r->domain,
1445  s5r->url);
1446  s5r->curl_paused = GNUNET_YES;
1447  return CURL_WRITEFUNC_PAUSE; /* not yet ready for data download */
1448  }
1449  if (sizeof(s5r->io_buf) - s5r->io_len < total)
1450  {
1452  "Pausing CURL `%s%s' download, not enough space %llu %llu %llu\n",
1453  s5r->domain,
1454  s5r->url,
1455  (unsigned long long) sizeof(s5r->io_buf),
1456  (unsigned long long) s5r->io_len,
1457  (unsigned long long) total);
1458  s5r->curl_paused = GNUNET_YES;
1459  return CURL_WRITEFUNC_PAUSE; /* not enough space */
1460  }
1461  GNUNET_memcpy (&s5r->io_buf[s5r->io_len],
1462  ptr,
1463  total);
1464  s5r->io_len += total;
1465  if (GNUNET_YES == s5r->suspended)
1466  {
1467  MHD_resume_connection (s5r->con);
1468  s5r->suspended = GNUNET_NO;
1469  }
1471  "Received %llu bytes of payload via cURL from %s\n",
1472  (unsigned long long) total,
1473  s5r->domain);
1474  if (s5r->io_len == total)
1475  run_mhd_now (s5r->hd);
1476  return total;
1477 }
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_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
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.
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).
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 1491 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().

1495 {
1496  struct Socks5Request *s5r = cls;
1497  size_t len = size * nmemb;
1498  size_t to_copy;
1499 
1501  "Receiving %ux%u bytes for `%s%s' from cURL to upload\n",
1502  (unsigned int) size,
1503  (unsigned int) nmemb,
1504  s5r->domain,
1505  s5r->url);
1506 
1507  if ((0 == s5r->io_len) &&
1508  (SOCKS5_SOCKET_UPLOAD_DONE != s5r->state))
1509  {
1511  "Pausing CURL UPLOAD %s%s, need more data\n",
1512  s5r->domain,
1513  s5r->url);
1514  return CURL_READFUNC_PAUSE;
1515  }
1516  if ((0 == s5r->io_len) &&
1517  (SOCKS5_SOCKET_UPLOAD_DONE == s5r->state))
1518  {
1520  if (GNUNET_YES == s5r->curl_paused)
1521  {
1522  s5r->curl_paused = GNUNET_NO;
1523  curl_easy_pause (s5r->curl,
1524  CURLPAUSE_CONT);
1525  }
1527  "Completed CURL UPLOAD %s%s\n",
1528  s5r->domain,
1529  s5r->url);
1530  return 0; /* upload finished, can now download */
1531  }
1532  if ((SOCKS5_SOCKET_UPLOAD_STARTED != s5r->state) &&
1533  (SOCKS5_SOCKET_UPLOAD_DONE != s5r->state))
1534  {
1535  GNUNET_break (0);
1536  return CURL_READFUNC_ABORT;
1537  }
1538  to_copy = GNUNET_MIN (s5r->io_len,
1539  len);
1540  GNUNET_memcpy (buf,
1541  s5r->io_buf,
1542  to_copy);
1543  memmove (s5r->io_buf,
1544  &s5r->io_buf[to_copy],
1545  s5r->io_len - to_copy);
1546  s5r->io_len -= to_copy;
1547  if (s5r->io_len + to_copy == sizeof(s5r->io_buf))
1548  run_mhd_now (s5r->hd); /* got more space for upload now */
1549  return to_copy;
1550 }
int curl_paused
Did we pause CURL processing?
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
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.
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:93
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).
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 1649 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().

1650 {
1651  int running;
1652  int msgnum;
1653  struct CURLMsg *msg;
1654  CURLMcode mret;
1655  struct Socks5Request *s5r;
1656 
1657  curl_download_task = NULL;
1659  "Running CURL interaction\n");
1660  do
1661  {
1662  running = 0;
1663  mret = curl_multi_perform (curl_multi,
1664  &running);
1666  "Checking CURL multi status: %d\n",
1667  mret);
1668  while (NULL != (msg = curl_multi_info_read (curl_multi,
1669  &msgnum)))
1670  {
1671  GNUNET_break (CURLE_OK ==
1672  curl_easy_getinfo (msg->easy_handle,
1673  CURLINFO_PRIVATE,
1674  (char **) &s5r));
1675  if (NULL == s5r)
1676  {
1677  GNUNET_break (0);
1678  continue;
1679  }
1680  switch (msg->msg)
1681  {
1682  case CURLMSG_NONE:
1683  /* documentation says this is not used */
1684  GNUNET_break (0);
1685  break;
1686 
1687  case CURLMSG_DONE:
1688  switch (msg->data.result)
1689  {
1690  case CURLE_OK:
1691  case CURLE_GOT_NOTHING:
1693  "CURL download %s%s completed.\n",
1694  s5r->domain,
1695  s5r->url);
1696  if (NULL == s5r->response)
1697  {
1700  }
1702  if (GNUNET_YES == s5r->suspended)
1703  {
1704  MHD_resume_connection (s5r->con);
1705  s5r->suspended = GNUNET_NO;
1706  }
1707  run_mhd_now (s5r->hd);
1708  break;
1709 
1710  default:
1712  "Download curl %s%s failed: %s\n",
1713  s5r->domain,
1714  s5r->url,
1715  curl_easy_strerror (msg->data.result));
1716  /* FIXME: indicate error somehow? close MHD connection badly as well? */
1718  if (GNUNET_YES == s5r->suspended)
1719  {
1720  MHD_resume_connection (s5r->con);
1721  s5r->suspended = GNUNET_NO;
1722  }
1723  run_mhd_now (s5r->hd);
1724  break;
1725  }
1726  if (NULL == s5r->response)
1728  break;
1729 
1730  case CURLMSG_LAST:
1731  /* documentation says this is not used */
1732  GNUNET_break (0);
1733  break;
1734 
1735  default:
1736  /* unexpected status code */
1737  GNUNET_break (0);
1738  break;
1739  }
1740  }
1741  ;
1742  }
1743  while (mret == CURLM_CALL_MULTI_PERFORM);
1744  if (CURLM_OK != mret)
1746  "%s failed at %s:%d: `%s'\n",
1747  "curl_multi_perform", __FILE__, __LINE__,
1748  curl_multi_strerror (mret));
1749  if (0 == running)
1750  {
1752  "Suspending cURL multi loop, no more events pending\n");
1753  if (NULL != curl_download_task)
1754  {
1756  curl_download_task = NULL;
1757  }
1758  return; /* nothing more in progress */
1759  }
1761 }
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_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,...)
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:972
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 1781 of file gnunet-gns-proxy.c.

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

Referenced by create_response().

1785 {
1786  struct Socks5Request *s5r = cls;
1787  char *hdr;
1788 
1789  if ((0 == strcasecmp (MHD_HTTP_HEADER_HOST,
1790  key)) &&
1791  (NULL != s5r->leho))
1792  value = s5r->leho;
1793  GNUNET_asprintf (&hdr,
1794  "%s: %s",
1795  key,
1796  value);
1798  "Adding HEADER `%s' to HTTP request\n",
1799  hdr);
1800  s5r->headers = curl_slist_append (s5r->headers,
1801  hdr);
1802  GNUNET_free (hdr);
1803  return MHD_YES;
1804 }
static char * value
Value of the record to add/remove.
struct curl_slist * headers
HTTP request headers for the curl request.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
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 MHD_RESULT 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 ("HTTP/1.1" for version 1.1, etc.)
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 1831 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().

1839 {
1840  struct Socks5Request *s5r = *con_cls;
1841  char *curlurl;
1842  char ipstring[INET6_ADDRSTRLEN];
1843  char ipaddr[INET6_ADDRSTRLEN + 2];
1844  char *curl_hosts;
1845  const struct sockaddr *sa;
1846  const struct sockaddr_in *s4;
1847  const struct sockaddr_in6 *s6;
1848  uint16_t port;
1849  size_t left;
1850 
1851  if (NULL == s5r)
1852  {
1853  GNUNET_break (0);
1854  return MHD_NO;
1855  }
1856  s5r->con = con;
1857  /* Fresh connection. */
1858  if (SOCKS5_SOCKET_WITH_MHD == s5r->state)
1859  {
1860  /* first time here, initialize curl handle */
1861  if (s5r->is_gns)
1862  {
1863  sa = (const struct sockaddr *) &s5r->destination_address;
1864  switch (sa->sa_family)
1865  {
1866  case AF_INET:
1867  s4 = (const struct sockaddr_in *) &s5r->destination_address;
1868  if (NULL == inet_ntop (AF_INET,
1869  &s4->sin_addr,
1870  ipstring,
1871  sizeof(ipstring)))
1872  {
1873  GNUNET_break (0);
1874  return MHD_NO;
1875  }
1876  GNUNET_snprintf (ipaddr,
1877  sizeof(ipaddr),
1878  "%s",
1879  ipstring);
1880  port = ntohs (s4->sin_port);
1881  break;
1882 
1883  case AF_INET6:
1884  s6 = (const struct sockaddr_in6 *) &s5r->destination_address;
1885  if (NULL == inet_ntop (AF_INET6,
1886  &s6->sin6_addr,
1887  ipstring,
1888  sizeof(ipstring)))
1889  {
1890  GNUNET_break (0);
1891  return MHD_NO;
1892  }
1893  GNUNET_snprintf (ipaddr,
1894  sizeof(ipaddr),
1895  "%s",
1896  ipstring);
1897  port = ntohs (s6->sin6_port);
1898  break;
1899 
1900  default:
1901  GNUNET_break (0);
1902  return MHD_NO;
1903  }
1904  GNUNET_asprintf (&curl_hosts,
1905  "%s:%d:%s",
1906  s5r->leho,
1907  port,
1908  ipaddr);
1909  s5r->hosts = curl_slist_append (NULL,
1910  curl_hosts);
1911  GNUNET_free (curl_hosts);
1912  }
1913  else
1914  {
1915  port = s5r->port;
1916  }
1917  if (NULL == s5r->curl)
1918  s5r->curl = curl_easy_init ();
1919  if (NULL == s5r->curl)
1920  return MHD_queue_response (con,
1921  MHD_HTTP_INTERNAL_SERVER_ERROR,
1923  curl_easy_setopt (s5r->curl,
1924  CURLOPT_HEADERFUNCTION,
1925  &curl_check_hdr);
1926  curl_easy_setopt (s5r->curl,
1927  CURLOPT_HEADERDATA,
1928  s5r);
1929  curl_easy_setopt (s5r->curl,
1930  CURLOPT_FOLLOWLOCATION,
1931  0);
1932  if (s5r->is_gns)
1933  curl_easy_setopt (s5r->curl,
1934  CURLOPT_IPRESOLVE,
1935  CURL_IPRESOLVE_V4);
1936  curl_easy_setopt (s5r->curl,
1937  CURLOPT_CONNECTTIMEOUT,
1938  600L);
1939  curl_easy_setopt (s5r->curl,
1940  CURLOPT_TIMEOUT,
1941  600L);
1942  curl_easy_setopt (s5r->curl,
1943  CURLOPT_NOSIGNAL,
1944  1L);
1945  curl_easy_setopt (s5r->curl,
1946  CURLOPT_HTTP_CONTENT_DECODING,
1947  0);
1948  curl_easy_setopt (s5r->curl,
1949  CURLOPT_NOSIGNAL,
1950  1L);
1951  curl_easy_setopt (s5r->curl,
1952  CURLOPT_PRIVATE,
1953  s5r);
1954  curl_easy_setopt (s5r->curl,
1955  CURLOPT_VERBOSE,
1956  0L);
1962  if ((NULL != s5r->leho) &&
1963  (NULL != s5r->hosts))
1964  {
1965  curl_easy_setopt (s5r->curl,
1966  CURLOPT_RESOLVE,
1967  s5r->hosts);
1968  }
1969  if (s5r->is_gns)
1970  {
1971  GNUNET_asprintf (&curlurl,
1972  (GNUNET_YES != s5r->is_tls) // (HTTPS_PORT != s5r->port)
1973  ? "http://%s:%d%s"
1974  : "https://%s:%d%s",
1975  (NULL != s5r->leho)
1976  ? s5r->leho
1977  : ipaddr,
1978  port,
1979  s5r->url);
1980  }
1981  else
1982  {
1983  GNUNET_asprintf (&curlurl,
1984  (GNUNET_YES != s5r->is_tls) // (HTTPS_PORT != s5r->port)
1985  ? "http://%s:%d%s"
1986  : "https://%s:%d%s",
1987  s5r->domain,
1988  port,
1989  s5r->url);
1990  }
1991  curl_easy_setopt (s5r->curl,
1992  CURLOPT_URL,
1993  curlurl);
1995  "Launching %s CURL interaction, fetching `%s'\n",
1996  (s5r->is_gns) ? "GNS" : "DNS",
1997  curlurl);
1998  GNUNET_free (curlurl);
1999  if (0 == strcasecmp (meth,
2000  MHD_HTTP_METHOD_PUT))
2001  {
2003  curl_easy_setopt (s5r->curl,
2004  CURLOPT_UPLOAD,
2005  1L);
2006  curl_easy_setopt (s5r->curl,
2007  CURLOPT_WRITEFUNCTION,
2008  &curl_download_cb);
2009  curl_easy_setopt (s5r->curl,
2010  CURLOPT_WRITEDATA,
2011  s5r);
2012  GNUNET_assert (CURLE_OK ==
2013  curl_easy_setopt (s5r->curl,
2014  CURLOPT_READFUNCTION,
2015  &curl_upload_cb));
2016  curl_easy_setopt (s5r->curl,
2017  CURLOPT_READDATA,
2018  s5r);
2019  {
2020  const char *us;
2021  long upload_size = 0;
2022 
2023  us = MHD_lookup_connection_value (con,
2024  MHD_HEADER_KIND,
2025  MHD_HTTP_HEADER_CONTENT_LENGTH);
2026  if ((1 == sscanf (us,
2027  "%ld",
2028  &upload_size)) &&
2029  (upload_size >= 0))
2030  {
2031  curl_easy_setopt (s5r->curl,
2032  CURLOPT_INFILESIZE,
2033  upload_size);
2034  }
2035  }
2036  }
2037  else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_POST))
2038  {
2040  curl_easy_setopt (s5r->curl,
2041  CURLOPT_POST,
2042  1L);
2043  curl_easy_setopt (s5r->curl,
2044  CURLOPT_WRITEFUNCTION,
2045  &curl_download_cb);
2046  curl_easy_setopt (s5r->curl,
2047  CURLOPT_WRITEDATA,
2048  s5r);
2049  curl_easy_setopt (s5r->curl,
2050  CURLOPT_READFUNCTION,
2051  &curl_upload_cb);
2052  curl_easy_setopt (s5r->curl,
2053  CURLOPT_READDATA,
2054  s5r);
2055  {
2056  const char *us;
2057  long upload_size;
2058 
2059  upload_size = 0;
2060  us = MHD_lookup_connection_value (con,
2061  MHD_HEADER_KIND,
2062  MHD_HTTP_HEADER_CONTENT_LENGTH);
2063  if ((NULL != us) &&
2064  (1 == sscanf (us,
2065  "%ld",
2066  &upload_size)) &&
2067  (upload_size >= 0))
2068  {
2069  curl_easy_setopt (s5r->curl,
2070  CURLOPT_INFILESIZE,
2071  upload_size);
2072  }
2073  else
2074  {
2075  curl_easy_setopt (s5r->curl,
2076  CURLOPT_INFILESIZE,
2077  upload_size);
2078  }
2079  }
2080  }
2081  else if (0 == strcasecmp (meth,
2082  MHD_HTTP_METHOD_HEAD))
2083  {
2085  curl_easy_setopt (s5r->curl,
2086  CURLOPT_NOBODY,
2087  1L);
2088  }
2089  else if (0 == strcasecmp (meth,
2090  MHD_HTTP_METHOD_OPTIONS))
2091  {
2093  curl_easy_setopt (s5r->curl,
2094  CURLOPT_CUSTOMREQUEST,
2095  "OPTIONS");
2096  curl_easy_setopt (s5r->curl,
2097  CURLOPT_WRITEFUNCTION,
2098  &curl_download_cb);
2099  curl_easy_setopt (s5r->curl,
2100  CURLOPT_WRITEDATA,
2101  s5r);
2102  }
2103  else if (0 == strcasecmp (meth,
2104  MHD_HTTP_METHOD_GET))
2105  {
2107  curl_easy_setopt (s5r->curl,
2108  CURLOPT_HTTPGET,
2109  1L);
2110  curl_easy_setopt (s5r->curl,
2111  CURLOPT_WRITEFUNCTION,
2112  &curl_download_cb);
2113  curl_easy_setopt (s5r->curl,
2114  CURLOPT_WRITEDATA,
2115  s5r);
2116  }
2117  else if (0 == strcasecmp (meth,
2118  MHD_HTTP_METHOD_DELETE))
2119  {
2121  curl_easy_setopt (s5r->curl,
2122  CURLOPT_CUSTOMREQUEST,
2123  "DELETE");
2124  curl_easy_setopt (s5r->curl,
2125  CURLOPT_WRITEFUNCTION,
2126  &curl_download_cb);
2127  curl_easy_setopt (s5r->curl,
2128  CURLOPT_WRITEDATA,
2129  s5r);
2130  }
2131  else
2132  {
2134  _ ("Unsupported HTTP method `%s'\n"),
2135  meth);
2136  curl_easy_cleanup (s5r->curl);
2137  s5r->curl = NULL;
2138  return MHD_NO;
2139  }
2140 
2141  if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_0))
2142  {
2143  curl_easy_setopt (s5r->curl,
2144  CURLOPT_HTTP_VERSION,
2145  CURL_HTTP_VERSION_1_0);
2146  }
2147  else if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_1))
2148  {
2149  curl_easy_setopt (s5r->curl,
2150  CURLOPT_HTTP_VERSION,
2151  CURL_HTTP_VERSION_1_1);
2152  }
2153  else
2154  {
2155  curl_easy_setopt (s5r->curl,
2156  CURLOPT_HTTP_VERSION,
2157  CURL_HTTP_VERSION_NONE);
2158  }
2159 
2160  if (GNUNET_YES == s5r->is_tls) // (HTTPS_PORT == s5r->port)
2161  {
2162  curl_easy_setopt (s5r->curl,
2163  CURLOPT_USE_SSL,
2164  CURLUSESSL_ALL);
2165  if (0 < s5r->num_danes)
2166  curl_easy_setopt (s5r->curl,
2167  CURLOPT_SSL_VERIFYPEER,
2168  0L);
2169  else
2170  curl_easy_setopt (s5r->curl,
2171  CURLOPT_SSL_VERIFYPEER,
2172  1L);
2173  /* Disable cURL checking the hostname, as we will check ourselves
2174  as only we have the domain name or the LEHO or the DANE record */
2175  curl_easy_setopt (s5r->curl,
2176  CURLOPT_SSL_VERIFYHOST,
2177  0L);
2178  }
2179  else
2180  {
2181  curl_easy_setopt (s5r->curl,
2182  CURLOPT_USE_SSL,
2183  CURLUSESSL_NONE);
2184  }
2185 
2186  if (CURLM_OK !=
2187  curl_multi_add_handle (curl_multi,
2188  s5r->curl))
2189  {
2190  GNUNET_break (0);
2191  curl_easy_cleanup (s5r->curl);
2192  s5r->curl = NULL;
2193  return MHD_NO;
2194  }
2195  MHD_get_connection_values (con,
2196  MHD_HEADER_KIND,
2197  (MHD_KeyValueIterator) & con_val_iter,
2198  s5r);
2199  curl_easy_setopt (s5r->curl,
2200  CURLOPT_HTTPHEADER,
2201  s5r->headers);
2203  return MHD_YES;
2204  }
2205 
2206  /* continuing to process request */
2207  if (0 != *upload_data_size)
2208  {
2210  "Processing %u bytes UPLOAD\n",
2211  (unsigned int) *upload_data_size);
2212 
2213  /* FIXME: This must be set or a header with Transfer-Encoding: chunked. Else
2214  * upload callback is not called!
2215  */
2216  curl_easy_setopt (s5r->curl,
2217  CURLOPT_POSTFIELDSIZE,
2218  *upload_data_size);
2219 
2220  left = GNUNET_MIN (*upload_data_size,
2221  sizeof(s5r->io_buf) - s5r->io_len);
2222  GNUNET_memcpy (&s5r->io_buf[s5r->io_len],
2223  upload_data,
2224  left);
2225  s5r->io_len += left;
2226  *upload_data_size -= left;
2227  GNUNET_assert (NULL != s5r->curl);
2228  if (GNUNET_YES == s5r->curl_paused)
2229  {
2230  s5r->curl_paused = GNUNET_NO;
2231  curl_easy_pause (s5r->curl,
2232  CURLPAUSE_CONT);
2233  }
2234  return MHD_YES;
2235  }
2236  if (SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state)
2237  {
2239  "Finished processing UPLOAD\n");
2241  }
2242  if (NULL == s5r->response)
2243  {
2245  "Waiting for HTTP response for %s%s...\n",
2246  s5r->domain,
2247  s5r->url);
2248  MHD_suspend_connection (con);
2249  s5r->suspended = GNUNET_YES;
2250  return MHD_YES;
2251  }
2253  "Queueing response for %s%s with MHD\n",
2254  s5r->domain,
2255  s5r->url);
2256  run_mhd_now (s5r->hd);
2257  return MHD_queue_response (con,
2258  s5r->response_code,
2259  s5r->response);
2260 }
Socket has been passed to MHD, do not close it anymore.
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_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
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:178
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
static uint16_t port
The port the proxy is running on (default 7777)
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:93
char * domain
the domain name to server (only important for TLS)
struct MHD_Response * response
MHD response object for this request.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
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.
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 2276 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().

2280 {
2281  struct Socks5Request *s5r = *con_cls;
2282 
2283  if (NULL == s5r)
2284  return;
2285  if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe)
2287  "MHD encountered error handling request: %d\n",
2288  toe);
2289  if (NULL != s5r->curl)
2290  {
2292  "Removing cURL handle (MHD interaction complete)\n");
2293  curl_multi_remove_handle (curl_multi,
2294  s5r->curl);
2295  curl_slist_free_all (s5r->headers);
2296  s5r->headers = NULL;
2297  curl_easy_reset (s5r->curl);
2298  s5r->rbuf_len = 0;
2299  s5r->wbuf_len = 0;
2300  s5r->io_len = 0;
2302  }
2303  if ((NULL != s5r->response) &&
2304  (curl_failure_response != s5r->response))
2305  MHD_destroy_response (s5r->response);
2306  for (struct HttpResponseHeader *header = s5r->header_head;
2307  NULL != header;
2308  header = s5r->header_head)
2309  {
2311  s5r->header_tail,
2312  header);
2313  GNUNET_free (header->type);
2314  GNUNET_free (header->value);
2315  GNUNET_free (header);
2316  }
2318  "Finished request for %s\n",
2319  s5r->url);
2320  GNUNET_free (s5r->url);
2322  s5r->url = NULL;
2323  s5r->response = NULL;
2324  *con_cls = NULL;
2325 }
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 2338 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().

2342 {
2343  struct Socks5Request *s5r;
2344  const union MHD_ConnectionInfo *ci;
2345  int sock;
2346 
2347  switch (cnc)
2348  {
2349  case MHD_CONNECTION_NOTIFY_STARTED:
2350  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection started...\n");
2351  ci = MHD_get_connection_info (connection,
2352  MHD_CONNECTION_INFO_CONNECTION_FD);
2353  if (NULL == ci)
2354  {
2355  GNUNET_break (0);
2356  return;
2357  }
2358  sock = ci->connect_fd;
2359  for (s5r = s5r_head; NULL != s5r; s5r = s5r->next)
2360  {
2361  if (GNUNET_NETWORK_get_fd (s5r->sock) == sock)
2362  {
2364  "Context set...\n");
2365  s5r->ssl_checked = GNUNET_NO;
2366  *con_cls = s5r;
2367  break;
2368  }
2369  }
2370  break;
2371 
2372  case MHD_CONNECTION_NOTIFY_CLOSED:
2374  "Connection closed... cleaning up\n");
2375  s5r = *con_cls;
2376  if (NULL == s5r)
2377  {
2379  "Connection stale!\n");
2380  return;
2381  }
2382  cleanup_s5r (s5r);
2384  *con_cls = NULL;
2385  break;
2386 
2387  default:
2388  GNUNET_break (0);
2389  }
2390 }
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1077
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...
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 2407 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().

2410 {
2411  struct Socks5Request *s5r;
2412  const union MHD_ConnectionInfo *ci;
2413 
2414  ci = MHD_get_connection_info (connection,
2415  MHD_CONNECTION_INFO_SOCKET_CONTEXT);
2416  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing %s\n", url);
2417  if (NULL == ci)
2418  {
2419  GNUNET_break (0);
2420  return NULL;
2421  }
2422  s5r = ci->socket_context;
2423  if (NULL != s5r->url)
2424  {
2425  GNUNET_break (0);
2426  return NULL;
2427  }
2428  s5r->url = GNUNET_strdup (url);
2429  if (NULL != s5r->timeout_task)
2430  {
2432  s5r->timeout_task = NULL;
2433  }
2435  return s5r;
2436 }
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:972
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 2445 of file gnunet-gns-proxy.c.

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

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

2446 {
2449  hd);
2450  GNUNET_free (hd->domain);
2451  MHD_stop_daemon (hd->daemon);
2452  if (NULL != hd->httpd_task)
2453  {
2455  hd->httpd_task = NULL;
2456  }
2457  GNUNET_free (hd->proxy_cert);
2458  if (hd == httpd)
2459  httpd = NULL;
2460  GNUNET_free (hd);
2461 }
#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.
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:972
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 2470 of file gnunet-gns-proxy.c.

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

Referenced by schedule_httpd().

2471 {
2472  struct MhdHttpList *hd = cls;
2473 
2474  hd->httpd_task = NULL;
2475  kill_httpd (hd);
2476 }
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 2574 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().

2575 {
2576  struct MhdHttpList *hd = cls;
2577 
2578  hd->httpd_task = NULL;
2579  MHD_run (hd->daemon);
2580  schedule_httpd (hd);
2581 }
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 2496 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(), max, MHD_CACHE_TIMEOUT, GNUNET_TIME_Relative::rel_value_us, and timeout.

Referenced by do_httpd(), and setup_data_transfer().

2497 {
2498  fd_set rs;
2499  fd_set ws;
2500  fd_set es;
2501  struct GNUNET_NETWORK_FDSet *wrs;
2502  struct GNUNET_NETWORK_FDSet *wws;
2503  int max;
2504  int haveto;
2505  MHD_UNSIGNED_LONG_LONG timeout;
2506  struct GNUNET_TIME_Relative tv;
2507 
2508  FD_ZERO (&rs);
2509  FD_ZERO (&ws);
2510  FD_ZERO (&es);
2511  max = -1;
2512  if (MHD_YES !=
2513  MHD_get_fdset (hd->daemon,
2514  &rs,
2515  &ws,
2516  &es,
2517  &max))
2518  {
2519  kill_httpd (hd);
2520  return;
2521  }
2522  haveto = MHD_get_timeout (hd->daemon,
2523  &timeout);
2524  if (MHD_YES == haveto)
2525  tv.rel_value_us = (uint64_t) timeout * 1000LL;
2526  else
2528  if (-1 != max)
2529  {
2530  wrs = GNUNET_NETWORK_fdset_create ();
2531  wws = GNUNET_NETWORK_fdset_create ();
2532  GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
2533  GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
2534  }
2535  else
2536  {
2537  wrs = NULL;
2538  wws = NULL;
2539  }
2540  if (NULL != hd->httpd_task)
2541  {
2543  hd->httpd_task = NULL;
2544  }
2545  if ((MHD_YES != haveto) &&
2546  (-1 == max) &&
2547  (hd != httpd))
2548  {
2549  /* daemon is idle, kill after timeout */
2551  &kill_httpd_task,
2552  hd);
2553  }
2554  else
2555  {
2556  hd->httpd_task =
2558  tv, wrs, wws,
2559  &do_httpd, hd);
2560  }
2561  if (NULL != wrs)
2563  if (NULL != wws)
2565 }
#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:1117
#define max(x, y)
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1263
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:1269
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1247
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
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:1841
#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:972
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 2607 of file gnunet-gns-proxy.c.

References GNUNET_DISK_file_size(), GNUNET_DISK_fn_read(), GNUNET_free, GNUNET_malloc, GNUNET_OK, GNUNET_YES, consensus-simulation::int, and MAX_PEM_SIZE.

Referenced by load_cert_from_file(), and load_key_from_file().

2609 {
2610  void *buffer;
2611  uint64_t fsize;
2612 
2613  if (GNUNET_OK !=
2615  &fsize,
2616  GNUNET_YES,
2617  GNUNET_YES))
2618  return NULL;
2619  if (fsize > MAX_PEM_SIZE)
2620  return NULL;
2621  *size = (unsigned int) fsize;
2622  buffer = GNUNET_malloc (*size);
2623  if (fsize !=
2625  buffer,
2626  (size_t) fsize))
2627  {
2628  GNUNET_free (buffer);
2629  return NULL;
2630  }
2631  return buffer;
2632 }
#define MAX_PEM_SIZE
Largest allowed size for a PEM certificate.
static char * filename
static unsigned int size
Size of the "table".
Definition: peer.c:67
enum GNUNET_GenericReturnValue 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:222
#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:664
#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 2643 of file gnunet-gns-proxy.c.

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

Referenced by run().

2645 {
2646  gnutls_datum_t key_data;
2647  int ret;
2648 
2649  key_data.data = load_file (keyfile,
2650  &key_data.size);
2651  if (NULL == key_data.data)
2652  return GNUNET_SYSERR;
2653  ret = gnutls_x509_privkey_import (key, &key_data,
2654  GNUTLS_X509_FMT_PEM);
2655  if (GNUTLS_E_SUCCESS != ret)
2656  {
2658  _ ("Unable to import private key from file `%s'\n"),
2659  keyfile);
2660  }
2661  GNUNET_free (key_data.data);
2662  return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK;
2663 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
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_log(kind,...)
#define GNUNET_free(ptr)
Wrapper around free.
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 2674 of file gnunet-gns-proxy.c.

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

Referenced by run().

2676 {
2677  gnutls_datum_t cert_data;
2678  int ret;
2679 
2680  cert_data.data = load_file (certfile,
2681  &cert_data.size);
2682  if (NULL == cert_data.data)
2683  return GNUNET_SYSERR;
2684  ret = gnutls_x509_crt_import (crt,
2685  &cert_data,
2686  GNUTLS_X509_FMT_PEM);
2687  if (GNUTLS_E_SUCCESS != ret)
2688  {
2690  _ ("Unable to import certificate from `%s'\n"),
2691  certfile);
2692  }
2693  GNUNET_free (cert_data.data);
2694  return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK;
2695 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
static void * load_file(const char *filename, unsigned int *size)
Read file in filename.
#define GNUNET_log(kind,...)
#define GNUNET_free(ptr)
Wrapper around free.
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 2705 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().

2706 {
2707  unsigned int serial;
2708  size_t key_buf_size;
2709  size_t cert_buf_size;
2710  gnutls_x509_crt_t request;
2711  time_t etime;
2712  struct tm *tm_data;
2713  struct ProxyGNSCertificate *pgc;
2714 
2716  "Generating x.509 certificate for `%s'\n",
2717  name);
2718  GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_init (&request));
2719  GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_set_key (request,
2720  proxy_ca.key));
2721  pgc = GNUNET_new (struct ProxyGNSCertificate);
2722  gnutls_x509_crt_set_dn_by_oid (request,
2723  GNUTLS_OID_X520_COUNTRY_NAME,
2724  0,
2725  "ZZ",
2726  strlen ("ZZ"));
2727  gnutls_x509_crt_set_dn_by_oid (request,
2728  GNUTLS_OID_X520_ORGANIZATION_NAME,
2729  0,
2730  "GNU Name System",
2731  strlen ("GNU Name System"));
2732  gnutls_x509_crt_set_dn_by_oid (request,
2733  GNUTLS_OID_X520_COMMON_NAME,
2734  0,
2735  name,
2736  strlen (name));
2737  gnutls_x509_crt_set_subject_alternative_name (request,
2738  GNUTLS_SAN_DNSNAME,
2739  name);
2740  GNUNET_break (GNUTLS_E_SUCCESS ==
2741  gnutls_x509_crt_set_version (request,
2742  3));
2743  gnutls_rnd (GNUTLS_RND_NONCE,
2744  &serial,
2745  sizeof(serial));
2746  gnutls_x509_crt_set_serial (request,
2747  &serial,
2748  sizeof(serial));
2749  etime = time (NULL);
2750  tm_data = localtime (&etime);
2751  tm_data->tm_hour--;
2752  etime = mktime (tm_data);
2753  gnutls_x509_crt_set_activation_time (request,
2754  etime);
2755  tm_data->tm_year++;
2756  etime = mktime (tm_data);
2757  gnutls_x509_crt_set_expiration_time (request,
2758  etime);
2759  gnutls_x509_crt_sign2 (request,
2760  proxy_ca.cert,
2761  proxy_ca.key,
2762  GNUTLS_DIG_SHA512,
2763  0);
2764  key_buf_size = sizeof(pgc->key);
2765  cert_buf_size = sizeof(pgc->cert);
2766  gnutls_x509_crt_export (request,
2767  GNUTLS_X509_FMT_PEM,
2768  pgc->cert,
2769  &cert_buf_size);
2770  gnutls_x509_privkey_export (proxy_ca.key,
2771  GNUTLS_X509_FMT_PEM,
2772  pgc->key,
2773  &key_buf_size);
2774  gnutls_x509_crt_deinit (request);
2775  return pgc;
2776 }
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...
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.
const char * name
#define GNUNET_log(kind,...)
gnutls_x509_crt_t cert
The certificate.
static uint64_t etime
Expiration string converted to numeric value.
Definition: gnunet-abd.c:201
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 2787 of file gnunet-gns-proxy.c.

Referenced by lookup_ssl_httpd().

2790 {
2791  /* do nothing */
2792 }
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 2802 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().

2803 {
2804  struct MhdHttpList *hd;
2805  struct ProxyGNSCertificate *pgc;
2806 
2807  if (NULL == domain)
2808  {
2809  GNUNET_break (0);
2810  return NULL;
2811  }
2812  for (hd = mhd_httpd_head; NULL != hd; hd = hd->next)
2813  if ((NULL != hd->domain) &&
2814  (0 == strcmp (hd->domain, domain)))
2815  return hd;
2817  "Starting fresh MHD HTTPS instance for domain `%s'\n",
2818  domain);
2819  pgc = generate_gns_certificate (domain);
2820  hd = GNUNET_new (struct MhdHttpList);
2821  hd->is_ssl = GNUNET_YES;
2822  hd->domain = GNUNET_strdup (domain);
2823  hd->proxy_cert = pgc;
2824  hd->daemon = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SSL
2825  | MHD_USE_NO_LISTEN_SOCKET
2826  | MHD_ALLOW_SUSPEND_RESUME,
2827  0,
2828  NULL, NULL,
2829  &create_response, hd,
2830  MHD_OPTION_CONNECTION_TIMEOUT, (unsigned
2831  int) 16,
2832  MHD_OPTION_NOTIFY_COMPLETED, &mhd_completed_cb,
2833  NULL,
2834  MHD_OPTION_NOTIFY_CONNECTION,
2835  &mhd_connection_cb, NULL,
2836  MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback,
2837  NULL,
2838  MHD_OPTION_EXTERNAL_LOGGER,
2839  &mhd_error_log_callback, NULL,
2840  MHD_OPTION_HTTPS_MEM_KEY, pgc->key,
2841  MHD_OPTION_HTTPS_MEM_CERT, pgc->cert,
2842  MHD_OPTION_END);
2843  if (NULL == hd->daemon)
2844  {
2845  GNUNET_free (pgc);
2846  GNUNET_free (hd);
2847  return NULL;
2848  }
2851  hd);
2852  return hd;
2853 }
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,...)
static MHD_RESULT 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.
static struct ProxyGNSCertificate * generate_gns_certificate(const char *name)
Generate new certificate for specific name.
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 (e.g.

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

Parameters
clsthe struct Socks5Request *

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

References cleanup_s5r(), and Socks5Request::timeout_task.

Referenced by setup_data_transfer().

2865 {
2866  struct Socks5Request *s5r = cls;
2867 
2868  s5r->timeout_task = NULL;
2869  cleanup_s5r (s5r);
2870 }
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 2882 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_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().

2883 {
2884  struct MhdHttpList *hd;
2885  int fd;
2886  const struct sockaddr *addr;
2887  socklen_t len;
2888  char *domain;
2889 
2890  if (GNUNET_YES == s5r->is_tls)
2891  {
2892  GNUNET_asprintf (&domain,
2893  "%s",
2894  s5r->domain);
2895  hd = lookup_ssl_httpd (domain);
2896  if (NULL == hd)
2897  {
2899  _ ("Failed to start HTTPS server for `%s'\n"),
2900  s5r->domain);
2901  cleanup_s5r (s5r);
2902  GNUNET_free (domain);
2903  return;
2904  }
2905  }
2906  else
2907  {
2908  domain = NULL;
2909  GNUNET_assert (NULL != httpd);
2910  hd = httpd;
2911  }
2912  fd = GNUNET_NETWORK_get_fd (s5r->sock);
2913  addr = GNUNET_NETWORK_get_addr (s5r->sock);
2914  len = GNUNET_NETWORK_get_addrlen (s5r->sock);
2916  if (MHD_YES !=
2917  MHD_add_connection (hd->daemon,
2918  fd,
2919  addr,
2920  len))
2921  {
2923  _ ("Failed to pass client to MHD\n"));
2924  cleanup_s5r (s5r);
2925  GNUNET_free (domain);
2926  return;
2927  }
2928  s5r->hd = hd;
2929  schedule_httpd (hd);
2932  s5r);
2933  GNUNET_free (domain);
2934 }
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:1077
struct sockaddr * GNUNET_NETWORK_get_addr(const struct GNUNET_NETWORK_Handle *desc)
Return the sockaddr for this network handle.
Definition: network.c:1090
socklen_t GNUNET_NETWORK_get_addrlen(const struct GNUNET_NETWORK_Handle *desc)
Return sockaddr length for this network handle.
Definition: network.c:1103
#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 _(String)
GNU gettext support macro.
Definition: platform.h:178
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:1269
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.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
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 (e...
#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 2946 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().

2947 {
2948  struct Socks5Request *s5r = cls;
2949  ssize_t len;
2950 
2951  s5r->wtask = NULL;
2952  len = GNUNET_NETWORK_socket_send (s5r->sock,
2953  s5r->wbuf,
2954  s5r->wbuf_len);
2955  if (len <= 0)
2956  {
2957  /* write error: connection closed, shutdown, etc.; just clean up */
2959  "Write Error\n");
2960  cleanup_s5r (s5r);
2961  return;
2962  }
2963  memmove (s5r->wbuf,
2964  &s5r->wbuf[len],
2965  s5r->wbuf_len - len);
2966  s5r->wbuf_len -= len;
2967  if (s5r->wbuf_len > 0)
2968  {
2969  /* not done writing */
2970  s5r->wtask =
2972  s5r->sock,
2973  &do_write, s5r);
2974  return;
2975  }
2976 
2977  /* we're done writing, continue with state machine! */
2978 
2979  switch (s5r->state)
2980  {
2981  case SOCKS5_INIT:
2982  GNUNET_assert (0);
2983  break;
2984 
2985  case SOCKS5_REQUEST:
2986  GNUNET_assert (NULL != s5r->rtask);
2987  break;
2988 
2989  case SOCKS5_DATA_TRANSFER:
2990  setup_data_transfer (s5r);
2991  return;
2992 
2994  cleanup_s5r (s5r);
2995  return;
2996 
2997  default:
2998  GNUNET_break (0);
2999  break;
3000  }
3001 }
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:812
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:1588
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 3011 of file gnunet-gns-proxy.c.

References do_write(), GNUNET_assert, GNUNET_break, GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_UNIT_FOREVER_REL, Socks5ServerResponseMessage::reply, sc, Socks5Request::sock, SOCKS5_WRITE_THEN_CLEANUP, SOCKS_BUFFERSIZE, SOCKS_VERSION_5, Socks5Request::state, 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  GNUNET_break (0 == s5r->wbuf_len); /* Should happen first in any transmission, right? */
3018  sizeof(struct Socks5ServerResponseMessage));
3019  s_resp = (struct Socks5ServerResponseMessage *) &s5r->wbuf[s5r->wbuf_len];
3020  memset (s_resp, 0, sizeof(struct Socks5ServerResponseMessage));
3021  s_resp->version = SOCKS_VERSION_5;
3022  s_resp->reply = sc;
3024  if (NULL != s5r->wtask)
3025  s5r->wtask =
3027  s5r->sock,
3028  &do_write, s5r);
3029 }
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.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
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:1588
struct GNUNET_NETWORK_Handle * sock
The client socket.
uint8_t reply
Status code, an enum Socks5StatusCode
#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.
enum SocksPhase state
The socks state.
#define SOCKS_BUFFERSIZE
Size of the read/write buffers for Socks.
#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 3038 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().

3039 {
3040  struct Socks5ServerResponseMessage *s_resp;
3041 
3042  s_resp = (struct Socks5ServerResponseMessage *) &s5r->wbuf[s5r->wbuf_len];
3043  s_resp->version = SOCKS_VERSION_5;
3045  s_resp->reserved = 0;
3046  s_resp->addr_type = SOCKS5_AT_IPV4;
3047  /* zero out IPv4 address and port */
3048  memset (&s_resp[1],
3049  0,
3050  sizeof(struct in_addr) + sizeof(uint16_t));
3051  s5r->wbuf_len += sizeof(struct Socks5ServerResponseMessage)
3052  + sizeof(struct in_addr) + sizeof(uint16_t);
3053  if (NULL == s5r->wtask)
3054  s5r->wtask =
3056  s5r->sock,
3057  &do_write, s5r);
3058 }
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:1588
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 3070 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, 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().

3074 {
3075  struct Socks5Request *s5r = cls;
3076  const struct GNUNET_GNSRECORD_Data *r;
3077  int got_ip;
3078 
3079  s5r->gns_lookup = NULL;
3080  s5r->is_gns = tld;
3081  got_ip = GNUNET_NO;
3082  for (uint32_t i = 0; i < rd_count; i++)
3083  {
3084  r = &rd[i];
3085  switch (r->record_type)
3086  {
3088  {
3089  struct sockaddr_in *in;
3090 
3091  if (sizeof(struct in_addr) != r->data_size)
3092  {
3093  GNUNET_break_op (0);
3094  break;
3095  }
3096  if (GNUNET_YES == got_ip)
3097  break;
3098  if (GNUNET_OK !=
3099  GNUNET_NETWORK_test_pf (PF_INET))
3100  break;
3101  got_ip = GNUNET_YES;
3102  in = (struct sockaddr_in *) &s5r->destination_address;
3103  in->sin_family = AF_INET;
3104  GNUNET_memcpy (&in->sin_addr,
3105  r->data,
3106  r->data_size);
3107  in->sin_port = htons (s5r->port);
3108 #if HAVE_SOCKADDR_IN_SIN_LEN
3109  in->sin_len = sizeof(*in);
3110 #endif
3111  }
3112  break;
3113 
3115  {
3116  struct sockaddr_in6 *in;
3117 
3118  if (sizeof(struct in6_addr) != r->data_size)
3119  {
3120  GNUNET_break_op (0);
3121  break;
3122  }
3123  if (GNUNET_YES == got_ip)
3124  break;
3125  if (GNUNET_YES == disable_v6)
3126  break;
3127  if (GNUNET_OK !=
3128  GNUNET_NETWORK_test_pf (PF_INET6))
3129  break;
3130  /* FIXME: allow user to disable IPv6 per configuration option... */
3131  got_ip = GNUNET_YES;
3132  in = (struct sockaddr_in6 *) &s5r->destination_address;
3133  in->sin6_family = AF_INET6;
3134  GNUNET_memcpy (&in->sin6_addr,
3135  r->data,
3136  r->data_size);
3137  in->sin6_port = htons (s5r->port);
3138 #if HAVE_SOCKADDR_IN_SIN_LEN
3139  in->sin6_len = sizeof(*in);
3140 #endif
3141  }
3142  break;
3143 
3145  GNUNET_break (0); /* should have been translated within GNS */
3146  break;
3147 
3149  GNUNET_free (s5r->leho);
3150  s5r->leho = GNUNET_strndup (r->data,
3151  r->data_size);
3152  break;
3153 
3155  {
3156  const struct GNUNET_GNSRECORD_BoxRecord *box;
3157 
3158  if (r->data_size < sizeof(struct GNUNET_GNSRECORD_BoxRecord))
3159  {
3160  GNUNET_break_op (0);
3161  break;
3162  }
3163  box = r->data;
3164  if ((ntohl (box->record_type) != GNUNET_DNSPARSER_TYPE_TLSA) ||
3165  (ntohs (box->protocol) != IPPROTO_TCP) ||
3166  (ntohs (box->service) != s5r->port))
3167  break; /* BOX record does not apply */
3168  if (s5r->num_danes >= MAX_DANES)
3169  {
3170  GNUNET_break (0); /* MAX_DANES too small */
3171  break;
3172  }
3173  s5r->is_tls = GNUNET_YES; /* This should be TLS */
3174  s5r->dane_data_len[s5r->num_danes]
3175  = r->data_size - sizeof(struct GNUNET_GNSRECORD_BoxRecord);
3176  s5r->dane_data[s5r->num_danes]
3177  = GNUNET_memdup (&box[1],
3178  s5r->dane_data_len[s5r->num_danes]);
3179  s5r->num_danes++;
3180  break;
3181  }
3182 
3183  default:
3184  /* don't care */
3185  break;
3186  }
3187  }
3188  if ((GNUNET_YES != got_ip) &&
3189  (GNUNET_YES == tld))
3190  {
3192  "Name resolution failed to yield useful IP address.\n");
3193  signal_socks_failure (s5r,
3195  return;
3196  }
3197  s5r->state = SOCKS5_DATA_TRANSFER;
3198  signal_socks_success (s5r);
3199 }
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_GNSRECORD_TYPE_BOX
Boxed records (see TLSA/SRV handling in GNS)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
#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_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_GNSRECORD_TYPE_LEHO
legacy hostnames
static void signal_socks_failure(struct Socks5Request *s5r, enum Socks5StatusCode sc)
Return a server response message indicating a failure to the client.
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.
#define GNUNET_GNSRECORD_TYPE_VPN
VPN resolution.
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_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.
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:85
#define GNUNET_free(ptr)
Wrapper around free.
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 3209 of file gnunet-gns-proxy.c.

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

Referenced by do_s5r_read().

3211 {
3212  GNUNET_assert (len <= s5r->rbuf_len);
3213  memmove (s5r->rbuf,
3214  &s5r->rbuf[len],
3215  s5r->rbuf_len - len);
3216  s5r->rbuf_len -= len;
3217 }
#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 3226 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_LO_LOCAL_MASTER, 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().

3227 {
3228  struct Socks5Request *s5r = cls;
3229  const struct Socks5ClientHelloMessage *c_hello;
3230  struct Socks5ServerHelloMessage *s_hello;
3231  const struct Socks5ClientRequestMessage *c_req;
3232  ssize_t rlen;
3233  size_t alen;
3234  const struct GNUNET_SCHEDULER_TaskContext *tc;
3235 
3236  s5r->rtask = NULL;
3238  if ((NULL != tc->read_ready) &&
3240  s5r->sock)))
3241  {
3242  rlen = GNUNET_NETWORK_socket_recv (s5r->sock,
3243  &s5r->rbuf[s5r->rbuf_len],
3244  sizeof(s5r->rbuf) - s5r->rbuf_len);
3245  if (rlen <= 0)
3246  {
3248  "socks5 client disconnected.\n");
3249  cleanup_s5r (s5r);
3250  return;
3251  }
3252  s5r->rbuf_len += rlen;
3253  }
3255  s5r->sock,
3256  &do_s5r_read, s5r);
3258  "Processing %zu bytes of socks data in state %d\n",
3259  s5r->rbuf_len,
3260  s5r->state);
3261  switch (s5r->state)
3262  {
3263  case SOCKS5_INIT:
3264  c_hello = (const struct Socks5ClientHelloMessage*) &s5r->rbuf;
3265  if ((s5r->rbuf_len < sizeof(struct Socks5ClientHelloMessage)) ||
3266  (s5r->rbuf_len < sizeof(struct Socks5ClientHelloMessage)
3267  + c_hello->num_auth_methods))
3268  return; /* need more data */
3269  if (SOCKS_VERSION_5 != c_hello->version)
3270  {
3272  _ ("Unsupported socks version %d\n"),
3273  (int) c_hello->version);
3274  cleanup_s5r (s5r);
3275  return;
3276  }
3277  clear_from_s5r_rbuf (s5r,
3278  sizeof(struct Socks5ClientHelloMessage)
3279  + c_hello->num_auth_methods);
3280  GNUNET_assert (0 == s5r->wbuf_len);
3281  s_hello = (struct Socks5ServerHelloMessage *) &s5r->wbuf;
3282  s5r->wbuf_len = sizeof(struct Socks5ServerHelloMessage);
3283  s_hello->version = SOCKS_VERSION_5;
3284  s_hello->auth_method = SOCKS_AUTH_NONE;
3285  GNUNET_assert (NULL == s5r->wtask);
3287  s5r->sock,
3288  &do_write, s5r);
3289  s5r->state = SOCKS5_REQUEST;
3290  return;
3291 
3292  case SOCKS5_REQUEST:
3293  c_req = (const struct Socks5ClientRequestMessage *) &s5r->rbuf;
3294  if (s5r->rbuf_len < sizeof(struct Socks5ClientRequestMessage))
3295  return;
3296  switch (c_req->command)
3297  {
3298  case SOCKS5_CMD_TCP_STREAM:
3299  /* handled below */
3300  break;
3301 
3302  default:
3304  _ ("Unsupported socks command %d\n"),
3305  (int) c_req->command);
3306  signal_socks_failure (s5r,
3308  return;
3309  }
3310  switch (c_req->addr_type)
3311  {
3312  case SOCKS5_AT_IPV4:
3313  {
3314  const struct in_addr *v4 = (const struct in_addr *) &c_req[1];
3315  const uint16_t *port = (const uint16_t *) &v4[1];
3316  struct sockaddr_in *in;
3317 
3318  s5r->port = ntohs (*port);
3319  alen = sizeof(struct in_addr);
3320  if (s5r->rbuf_len < sizeof(struct Socks5ClientRequestMessage)
3321  + alen + sizeof(uint16_t))
3322  return; /* need more data */
3323  in = (struct sockaddr_in *) &s5r->destination_address;
3324  in->sin_family = AF_INET;
3325  in->sin_addr = *v4;
3326  in->sin_port = *port;
3327 #if HAVE_SOCKADDR_IN_SIN_LEN
3328  in->sin_len = sizeof(*in);
3329 #endif
3330  s5r->state = SOCKS5_DATA_TRANSFER;
3331  }
3332  break;
3333 
3334  case SOCKS5_AT_IPV6:
3335  {
3336  const struct in6_addr *v6 = (const struct in6_addr *) &c_req[1];
3337  const uint16_t *port = (const uint16_t *) &v6[1];
3338  struct sockaddr_in6 *in;
3339 
3340  s5r->port = ntohs (*port);
3341  alen = sizeof(struct in6_addr);
3342  if (s5r->rbuf_len < sizeof(struct Socks5ClientRequestMessage)
3343  + alen + sizeof(uint16_t))
3344  return; /* need more data */
3345  in = (struct sockaddr_in6 *) &s5r->destination_address;
3346  in->sin6_family = AF_INET6;
3347  in->sin6_addr = *v6;
3348  in->sin6_port = *port;
3349 #if HAVE_SOCKADDR_IN_SIN_LEN
3350  in->sin6_len = sizeof(*in);
3351 #endif
3352  s5r->state = SOCKS5_DATA_TRANSFER;
3353  }
3354  break;
3355 
3356  case SOCKS5_AT_DOMAINNAME:
3357  {
3358  const uint8_t *dom_len;
3359  const char *dom_name;
3360  const uint16_t *port;
3361 
3362  dom_len = (const uint8_t *) &c_req[1];
3363  alen = *dom_len + 1;
3364  if (s5r->rbuf_len < sizeof(struct Socks5ClientRequestMessage)
3365  + alen + sizeof(uint16_t))
3366  return; /* need more data */
3367  dom_name = (const char *) &dom_len[1];
3368  port = (const uint16_t *) &dom_name[*dom_len];
3369  s5r->domain = GNUNET_strndup (dom_name,
3370  *dom_len);
3372  "Requested connection is to %s:%d\n",
3373  // (HTTPS_PORT == s5r->port) ? "s" : "",
3374  s5r->domain,
3375  ntohs (*port));
3376  s5r->state = SOCKS5_RESOLVING;
3377  s5r->port = ntohs (*port);
3378  s5r->is_tls = (HTTPS_PORT == s5r->port) ? GNUNET_YES : GNUNET_NO;
3380  s5r->domain,
3382  GNUNET_GNS_LO_LOCAL_MASTER /* only cached */,
3384  s5r);
3385  break;
3386  }
3387 
3388  default:
3390  _ ("Unsupported socks address type %d\n"),
3391  (int) c_req->addr_type);
3392  signal_socks_failure (s5r,
3394  return;
3395  }
3396  clear_from_s5r_rbuf (s5r,
3397  sizeof(struct Socks5ClientRequestMessage)
3398  + alen + sizeof(uint16_t));
3399  if (0 != s5r->rbuf_len)
3400  {
3401  /* read more bytes than healthy, why did the client send more!? */
3402  GNUNET_break_op (0);
3403  signal_socks_failure (s5r,
3405  return;
3406  }
3407  if (SOCKS5_DATA_TRANSFER == s5r->state)
3408  {
3409  /* if we are not waiting for GNS resolution, signal success */
3410  signal_socks_success (s5r);
3411  }
3412  /* We are done reading right now */
3414  s5r->rtask = NULL;
3415  return;
3416 
3417  case SOCKS5_RESOLVING:
3418  GNUNET_assert (0);
3419  return;
3420 
3421  case SOCKS5_DATA_TRANSFER:
3422  GNUNET_assert (0);
3423  return;
3424 
3425  default:
3426  GNUNET_assert (0);
3427  return;
3428  }
3429 }
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition: scheduler.c:752
For the rightmost label, only look in the cache (it is our local namestore), for the others...
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:783
#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:423
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:241
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:1588
struct GNUNET_NETWORK_Handle * sock
The client socket.
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:178
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.
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:1517
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:1026
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:972
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 3439 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().

3440 {
3441  struct GNUNET_NETWORK_Handle *lsock = cls;
3442  struct GNUNET_NETWORK_Handle *s;
3443  struct Socks5Request *s5r;
3444 
3445  GNUNET_assert (NULL != lsock);
3446  if (lsock == lsock4)
3448  lsock,
3449  &do_accept,
3450  lsock);
3451  else if (lsock == lsock6)
3453  lsock,
3454  &do_accept,
3455  lsock);
3456  else
3457  GNUNET_assert (0);
3458  s = GNUNET_NETWORK_socket_accept (lsock,
3459  NULL,
3460  NULL);
3461  if (NULL == s)
3462  {
3464  "accept");
3465  return;
3466  }
3468  "Got an inbound connection, waiting for data\n");
3469  s5r = GNUNET_new (struct Socks5Request);
3471  s5r_tail,
3472  s5r);
3473  s5r->sock = s;
3474  s5r->state = SOCKS5_INIT;
3476  s5r->sock,
3477  &do_s5r_read,
3478  s5r);
3479 }
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:430
#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:52
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:1517
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 3491 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().

3492 {
3494  "Shutting down...\n");
3495  /* MHD requires resuming before destroying the daemons */
3496  for (struct Socks5Request *s5r = s5r_head;
3497  NULL != s5r;
3498  s5r = s5r->next)
3499  {
3500  if (s5r->suspended)
3501  {
3502  s5r->suspended = GNUNET_NO;
3503  MHD_resume_connection (s5r->con);
3504  }
3505  }
3506  while (NULL != mhd_httpd_head)
3508  while (NULL != s5r_head)
3510  if (NULL != lsock4)
3511  {
3513  lsock4 = NULL;
3514  }
3515  if (NULL != lsock6)
3516  {
3518  lsock6 = NULL;
3519  }
3520  if (NULL != curl_multi)
3521  {
3522  curl_multi_cleanup (curl_multi);
3523  curl_multi = NULL;
3524  }
3525  if (NULL != gns_handle)
3526  {
3528  gns_handle = NULL;
3529  }
3530  if (NULL != curl_download_task)
3531  {
3533  curl_download_task = NULL;
3534  }
3535  if (NULL != ltask4)
3536  {
3538  ltask4 = NULL;
3539  }
3540  if (NULL != ltask6)
3541  {
3543  ltask6 = NULL;
3544  }
3545  gnutls_x509_crt_deinit (proxy_ca.cert);
3546  gnutls_x509_privkey_deinit (proxy_ca.key);
3547  gnutls_global_deinit ();
3548 }
static struct GNUNET_SCHEDULER_Task * ltask4
The listen task ID for IPv4.
static struct GNUNET_SCHEDULER_Task * ltask6
The listen task ID for IPv6.
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:290
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:560
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
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 3557 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().

3558 {
3559  struct GNUNET_NETWORK_Handle *ls;
3560  struct sockaddr_in sa4;
3561  int eno;
3562 
3563  memset (&sa4, 0, sizeof(sa4));
3564  sa4.sin_family = AF_INET;
3565  sa4.sin_port = htons (port);
3566  sa4.sin_addr.s_addr = address;
3567 #if HAVE_SOCKADDR_IN_SIN_LEN
3568  sa4.sin_len = sizeof(sa4);
3569 #endif
3570  ls = GNUNET_NETWORK_socket_create (AF_INET,
3571  SOCK_STREAM,
3572  0);
3573  if (NULL == ls)
3574  return NULL;
3575  if (GNUNET_OK !=
3577  (const struct sockaddr *) &sa4,
3578  sizeof(sa4)))
3579  {
3580  eno = errno;
3582  errno = eno;
3583  return NULL;
3584  }
3585  return ls;
3586 }
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:485
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:52
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:560
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:909
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 3595 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().

3596 {
3597  struct GNUNET_NETWORK_Handle *ls;
3598  struct sockaddr_in6 sa6;
3599  int eno;
3600 
3601  memset (&sa6, 0, sizeof(sa6));
3602  sa6.sin6_family = AF_INET6;
3603  sa6.sin6_port = htons (port);
3604  sa6.sin6_addr = address6;
3605 #if HAVE_SOCKADDR_IN_SIN_LEN
3606  sa6.sin6_len = sizeof(sa6);
3607 #endif
3608  ls = GNUNET_NETWORK_socket_create (AF_INET6,
3609  SOCK_STREAM,
3610  0);
3611  if (NULL == ls)
3612  return NULL;
3613  if (GNUNET_OK !=
3615  (const struct sockaddr *) &sa6,
3616  sizeof(sa6)))
3617  {
3618  eno = errno;
3620  errno = eno;
3621  return NULL;
3622  }
3623  return ls;
3624 }
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:485
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:52
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:560
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:909
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 3636 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_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, 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().

3640 {
3641  char*cafile_cfg = NULL;
3642  char*cafile;
3643  char*addr_str;
3644  struct MhdHttpList *hd;
3645 
3646  cfg = c;
3647 
3648  /* Get address to bind to */
3650  "BIND_TO",
3651  &addr_str))
3652  {
3653  // No address specified
3655  "Don't know what to bind to...\n");
3656  GNUNET_free (addr_str);
3658  return;
3659  }
3660  if (1 != inet_pton (AF_INET, addr_str, &address))
3661  {
3663  "Unable to parse address %s\n",
3664  addr_str);
3665  GNUNET_free (addr_str);
3667  return;
3668  }
3669  GNUNET_free (addr_str);
3670  /* Get address to bind to */
3672  "BIND_TO6",
3673  &addr_str))
3674  {
3675  // No address specified
3677  "Don't know what to bind6 to...\n");
3678  GNUNET_free (addr_str);
3680  return;
3681  }
3682  if (1 != inet_pton (AF_INET6, addr_str, &address6))
3683  {
3685  "Unable to parse IPv6 address %s\n",
3686  addr_str);
3687  GNUNET_free (addr_str);
3689  return;
3690  }
3691  GNUNET_free (addr_str);
3692 
3693  if (NULL == (curl_multi = curl_multi_init ()))
3694  {
3696  "Failed to create cURL multi handle!\n");
3697  return;
3698  }
3699  cafile = cafile_opt;
3700  if (NULL == cafile)
3701  {
3702  if (GNUNET_OK !=
3704  "gns-proxy",
3705  "PROXY_CACERT",
3706  &cafile_cfg))
3707  {
3709  "gns-proxy",
3710  "PROXY_CACERT");
3711  return;
3712  }
3713  cafile = cafile_cfg;
3714  }
3716  "Using `%s' as CA\n",
3717  cafile);
3718 
3719  gnutls_global_init ();
3720  gnutls_x509_crt_init (&proxy_ca.cert);
3721  gnutls_x509_privkey_init (&proxy_ca.key);
3722 
3723  if ((GNUNET_OK !=
3725  cafile)) ||
3726  (GNUNET_OK !=
3728  cafile)))
3729  {
3731  _ ("Failed to load X.509 key and certificate from `%s'\n"),
3732  cafile);
3733  gnutls_x509_crt_deinit (proxy_ca.cert);
3734  gnutls_x509_privkey_deinit (proxy_ca.key);
3735  gnutls_global_deinit ();
3736  GNUNET_free (cafile_cfg);
3737  return;
3738  }
3739  GNUNET_free (cafile_cfg);
3740  if (NULL == (gns_handle = GNUNET_GNS_connect (cfg)))
3741  {
3743  "Unable to connect to GNS!\n");
3744  gnutls_x509_crt_deinit (proxy_ca.cert);
3745  gnutls_x509_privkey_deinit (proxy_ca.key);
3746  gnutls_global_deinit ();
3747  return;
3748  }
3750  NULL);
3751 
3752  /* Open listen socket for socks proxy */
3753  lsock6 = bind_v6 ();
3754  if (NULL == lsock6)
3755  {
3757  "bind");
3758  }
3759  else
3760  {
3761  if (GNUNET_OK !=
3763  5))
3764  {
3766  "listen");
3768  lsock6 = NULL;
3769  }
3770  else
3771  {
3773  lsock6,
3774  &do_accept,
3775  lsock6);
3776  }
3777  }
3778  lsock4 = bind_v4 ();
3779  if (NULL == lsock4)
3780  {