GNUnet  0.11.x
socks.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009-2013 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 
31 
32 #define LOG(kind, ...) GNUNET_log_from (kind, "util-socks", __VA_ARGS__)
33 
34 #define LOG_STRERROR(kind, syscall) \
35  GNUNET_log_from_strerror (kind, "util-socks", syscall)
36 
37 
38 /* SOCKS5 authentication methods */
39 #define SOCKS5_AUTH_REJECT 0xFF /* No acceptable auth method */
40 #define SOCKS5_AUTH_NOAUTH 0x00 /* without authentication */
41 #define SOCKS5_AUTH_GSSAPI 0x01 /* GSSAPI */
42 #define SOCKS5_AUTH_USERPASS 0x02 /* User/Password */
43 #define SOCKS5_AUTH_CHAP 0x03 /* Challenge-Handshake Auth Proto. */
44 #define SOCKS5_AUTH_EAP 0x05 /* Extensible Authentication Proto. */
45 #define SOCKS5_AUTH_MAF 0x08 /* Multi-Authentication Framework */
46 
47 
48 /* SOCKS5 connection responces */
49 #define SOCKS5_REP_SUCCEEDED 0x00 /* succeeded */
50 #define SOCKS5_REP_FAIL 0x01 /* general SOCKS serer failure */
51 #define SOCKS5_REP_NALLOWED 0x02 /* connection not allowed by ruleset */
52 #define SOCKS5_REP_NUNREACH 0x03 /* Network unreachable */
53 #define SOCKS5_REP_HUNREACH 0x04 /* Host unreachable */
54 #define SOCKS5_REP_REFUSED 0x05 /* connection refused */
55 #define SOCKS5_REP_EXPIRED 0x06 /* TTL expired */
56 #define SOCKS5_REP_CNOTSUP 0x07 /* Command not supported */
57 #define SOCKS5_REP_ANOTSUP 0x08 /* Address not supported */
58 #define SOCKS5_REP_INVADDR 0x09 /* Inalid address */
59 
60 const char *
62 {
63  switch (rep)
64  {
66  return "succeeded";
67 
68  case SOCKS5_REP_FAIL:
69  return "general SOCKS server failure";
70 
72  return "connection not allowed by ruleset";
73 
75  return "Network unreachable";
76 
78  return "Host unreachable";
79 
80  case SOCKS5_REP_REFUSED:
81  return "connection refused";
82 
83  case SOCKS5_REP_EXPIRED:
84  return "TTL expired";
85 
86  case SOCKS5_REP_CNOTSUP:
87  return "Command not supported";
88 
89  case SOCKS5_REP_ANOTSUP:
90  return "Address not supported";
91 
92  case SOCKS5_REP_INVADDR:
93  return "Invalid address";
94 
95  default:
96  return NULL;
97  }
98 };
99 
100 
110 unsigned char *
111 SOCK5_proto_string (unsigned char *b, const char *s)
112 {
113  size_t l = strlen (s);
114 
115  if (l > 255)
116  {
118  "SOCKS5 cannot handle hostnames, usernames, or passwords over 255 bytes, truncating.\n");
119  l = 255;
120  }
121  *(b++) = (unsigned char) l;
122  memcpy (b, s, l);
123  return b + l;
124 }
125 
126 
127 #define SOCKS5_step_greet 0
128 #define SOCKS5_step_auth 1
129 #define SOCKS5_step_cmd 2
130 #define SOCKS5_step_done 3
131 
136 {
141 
146 
151 
155  int step;
156 
160  unsigned char outbuf[1024];
161 
165  unsigned char *(outstep[4]);
166 
170  unsigned char inbuf[1024];
171 
175  unsigned char *instart;
176  unsigned char *inend;
177 };
178 
179 
180 /* Regitering prototypes */
181 
182 void
183 register_reciever (struct GNUNET_SOCKS_Handshake *ih, int want);
184 
185 /* In fact, the client sends first rule in GNUnet suggests one could take
186  * large mac read sizes without fear of screwing up the proxied protocol,
187  * but we make a proper SOCKS5 client. */
188 #define register_reciever_wants(ih) ((SOCKS5_step_cmd == ih->step) ? 10 : 2)
189 
190 
193 
194 
202 void
204 {
206 }
207 
208 
214 void
216 {
217  unsigned char *b = ih->instart;
218  size_t available = ih->inend - b;
219 
220  int want = register_reciever_wants (ih);
221 
222  if (available < want)
223  {
224  register_reciever (ih, want - available);
225  return;
226  }
227  GNUNET_assert (SOCKS5_step_done > ih->step && ih->step >= 0);
228  switch (ih->step)
229  {
230  case SOCKS5_step_greet: /* SOCKS5 server's greeting */
231  if (b[0] != 5)
232  {
233  LOG (GNUNET_ERROR_TYPE_ERROR, "Not a SOCKS5 server\n");
234  GNUNET_assert (0);
235  }
236  switch (b[1])
237  {
238  case SOCKS5_AUTH_NOAUTH:
239  ih->step = SOCKS5_step_cmd; /* no authentication to do */
240  break;
241 
243  ih->step = SOCKS5_step_auth;
244  break;
245 
246  case SOCKS5_AUTH_REJECT:
247  LOG (GNUNET_ERROR_TYPE_ERROR, "No authentication method accepted\n");
248  return;
249 
250  default:
252  "Not a SOCKS5 server / Nonsensical authentication\n");
253  return;
254  }
255  b += 2;
256  break;
257 
258  case SOCKS5_step_auth: /* SOCKS5 server's responce to authentication */
259  if (b[1] != 0)
260  {
261  LOG (GNUNET_ERROR_TYPE_ERROR, "SOCKS5 authentication failed\n");
262  GNUNET_assert (0);
263  }
264  ih->step = SOCKS5_step_cmd;
265  b += 2;
266  break;
267 
268  case SOCKS5_step_cmd: /* SOCKS5 server's responce to command */
269  if (b[0] != 5)
270  {
271  LOG (GNUNET_ERROR_TYPE_ERROR, "SOCKS5 protocol error\n");
272  GNUNET_assert (0);
273  }
274  if (0 != b[1])
275  {
277  "SOCKS5 connection error : %s\n",
278  SOCKS5_REP_names (b[1]));
279  return;
280  }
281  b += 3;
282  /* There is no reason to verify host and port afaik. */
283  switch (*(b++))
284  {
285  case 1: /* IPv4 */
286  b += sizeof(struct in_addr); /* 4 */
287  break;
288 
289  case 4: /* IPv6 */
290  b += sizeof(struct in6_addr); /* 16 */
291  break;
292 
293  case 3: /* hostname */
294  b += *b;
295  break;
296  }
297  b += 2; /* port */
298  if (b > ih->inend)
299  {
300  register_reciever (ih, b - ih->inend);
301  return;
302  }
303  ih->step = SOCKS5_step_done;
305  "SOCKS5 server : %s\n",
306  SOCKS5_REP_names (b[1]));
307  ih->instart = b;
309  return;
310 
311  case SOCKS5_step_done:
312  GNUNET_assert (0);
313  }
314  ih->instart = b;
315  /* Do not reschedule the sender unless we're done reading.
316  * I imagine this lets us avoid ever cancelling the transmit handle. */
317  register_sender (ih);
318 }
319 
320 
328 void
329 reciever (void *cls,
330  const void *buf,
331  size_t available,
332  const struct sockaddr *addr,
333  socklen_t addrlen,
334  int errCode)
335 {
336  struct GNUNET_SOCKS_Handshake *ih = cls;
337 
338  GNUNET_assert (&ih->inend[available] < &ih->inbuf[1024]);
339  GNUNET_memcpy (ih->inend, buf, available);
340  ih->inend += available;
342 }
343 
344 
352 void
354 {
356  want,
358  &reciever,
359  ih);
360 }
361 
362 
371 size_t
372 transmit_ready (void *cls, size_t size, void *buf)
373 {
374  struct GNUNET_SOCKS_Handshake *ih = cls;
375 
376  /* connection.c has many routines that call us with buf == NULL :
377  * signal_transmit_error() - DNS, etc. active
378  * connect_fail_continuation()
379  * connect_probe_continuation() - timeout
380  * try_connect_using_address() - DNS failure/timeout
381  * transmit_timeout() - retry failed?
382  * GNUNET_CONNECTION_notify_transmit_ready() can schedule :
383  * transmit_timeout() - DNS still working
384  * connect_error() - DNS done but no socket?
385  * transmit_ready() - scheduler shutdown or timeout, or signal_transmit_error()
386  * We'd need to dig into the scheduler to guess at the reason, as
387  * connection.c tells us nothing itself, but mostly its timouts.
388  * Initially, we'll simply ignore this and leave massive timeouts, but
389  * maybe that should change for error handling pruposes. It appears that
390  * successful operations, including DNS resolution, do not use this. */if (NULL == buf)
391  {
392  if (0 == ih->step)
393  {
395  "Timeout contacting SOCKS server, retrying indefinitely, but probably hopeless.\n");
396  register_sender (ih);
397  }
398  else
399  {
401  "Timeout during mid SOCKS handshake (step %u), probably not a SOCKS server.\n",
402  ih->step);
403  GNUNET_break (0);
404  }
405  return 0;
406  }
407 
408  GNUNET_assert ((1024 >= size) && (size > 0));
409  GNUNET_assert ((SOCKS5_step_done > ih->step) && (ih->step >= 0));
410  unsigned char *b = ih->outstep[ih->step];
411  unsigned char *e = ih->outstep[ih->step + 1];
412  GNUNET_assert (e <= &ih->outbuf[1024]);
413  unsigned int l = e - b;
414  GNUNET_assert (size >= l);
415  GNUNET_memcpy (buf, b, l);
417  return l;
418 }
419 
420 
430 {
432 
434  GNUNET_assert (ih->step >= 0);
435  if (0 == ih->step)
437  unsigned char *b = ih->outstep[ih->step];
438  unsigned char *e = ih->outstep[ih->step + 1];
439  GNUNET_assert (ih->outbuf <= b && b < e && e < &ih->outbuf[1024]);
441  e - b,
442  timeout,
444  ih);
445  return ih->th;
446 }
447 
448 
458 struct GNUNET_SOCKS_Handshake *
459 GNUNET_SOCKS_init_handshake (const char *user, const char *pass)
460 {
461  struct GNUNET_SOCKS_Handshake *ih =
463  unsigned char *b = ih->outbuf;
464 
465  ih->outstep[SOCKS5_step_greet] = b;
466  *(b++) = 5; /* SOCKS5 */
467  unsigned char *n = b++;
468  *n = 1; /* Number of authentication methods */
469  /* We support no authentication even when requesting authentication,
470  * but this appears harmless, given the way that Tor uses authentication.
471  * And some SOCKS5 servers might require this. */
472  *(b++) = SOCKS5_AUTH_NOAUTH;
473  if (NULL != user)
474  {
475  *(b++) = SOCKS5_AUTH_USERPASS;
476  (*n)++;
477  }
478  /* There is no apperent reason to support authentication methods beyond
479  * username and password since afaik Tor does not support them. */
480 
481  /* We authenticate with an empty username and password if the server demands
482  * them but we do not have any. */
483  if (user == NULL)
484  user = "";
485  if (pass == NULL)
486  pass = "";
487 
488  ih->outstep[SOCKS5_step_auth] = b;
489  *(b++) = 1; /* subnegotiation ver.: 1 */
490  b = SOCK5_proto_string (b, user);
491  b = SOCK5_proto_string (b, pass);
492 
493  ih->outstep[SOCKS5_step_cmd] = b;
494 
495  ih->inend = ih->instart = ih->inbuf;
496 
497  return ih;
498 }
499 
500 
507 struct GNUNET_SOCKS_Handshake *
509 {
510  return GNUNET_SOCKS_init_handshake (NULL, NULL);
511 }
512 
513 
522 void
524  const char *host,
525  uint16_t port)
526 {
527  union
528  {
529  struct in_addr in4;
530  struct in6_addr in6;
531  } ia;
532  unsigned char *b = ih->outstep[SOCKS5_step_cmd];
533 
534  *(b++) = 5; /* SOCKS5 */
535  *(b++) = 1; /* Establish a TCP/IP stream */
536  *(b++) = 0; /* reserved */
537 
538  /* Specify destination */
539  if (1 == inet_pton (AF_INET, host, &ia.in4))
540  {
541  *(b++) = 1; /* IPv4 */
542  GNUNET_memcpy (b, &ia.in4, sizeof(struct in_addr));
543  b += sizeof(struct in_addr); /* 4 */
544  }
545  else if (1 == inet_pton (AF_INET6, host, &ia.in6))
546  {
547  *(b++) = 4; /* IPv6 */
548  GNUNET_memcpy (b, &ia.in6, sizeof(struct in6_addr));
549  b += sizeof(struct in6_addr); /* 16 */
550  }
551  else
552  {
553  *(b++) = 3; /* hostname */
554  b = SOCK5_proto_string (b, host);
555  }
556 
557  /* Specify port */
558  *(uint16_t *) b = htons (port);
559  b += 2;
560 
561  ih->outstep[SOCKS5_step_done] = b;
562 }
563 
564 
574  struct GNUNET_CONNECTION_Handle *c)
575 {
576  ih->socks5_connection = c;
578  register_sender (ih);
579 
580  return ih->target_connection;
581 }
582 
583 
592 int
594  const struct GNUNET_CONFIGURATION_Handle *cfg)
595 {
596  return GNUNET_CONFIGURATION_have_value (cfg, service_name, "SOCKSPORT") ||
597  GNUNET_CONFIGURATION_have_value (cfg, service_name, "SOCKSHOST");
598 }
599 
600 
611  const struct GNUNET_CONFIGURATION_Handle *cfg)
612 {
613  struct GNUNET_SOCKS_Handshake *ih;
614  struct GNUNET_CONNECTION_Handle *socks5; /* *proxied */
615  char *host0;
616  char *host1;
617  char *user;
618  char *pass;
619  unsigned long long port0;
620  unsigned long long port1;
621 
622  if (GNUNET_YES != GNUNET_SOCKS_check_service (service_name, cfg))
623  return NULL;
625  service_name,
626  "SOCKSPORT",
627  &port0))
628  port0 = 9050;
629  /* A typical Tor client should usually try port 9150 for the TBB too, but
630  * GNUnet can probably assume a system Tor installation. */
631  if ((port0 > 65535) || (port0 <= 0))
632  {
634  _ (
635  "Attempting to use invalid port %d as SOCKS proxy for service `%s'.\n"),
636  port0,
637  service_name);
638  return NULL;
639  }
641  service_name,
642  "PORT",
643  &port1)) ||
644  (port1 > 65535) || (port1 <= 0) ||
646  service_name,
647  "HOSTNAME",
648  &host1)))
649  {
651  _ (
652  "Attempting to proxy service `%s' to invalid port %d or hostname.\n"),
653  service_name,
654  port1);
655  return NULL;
656  }
657  /* Appeared to still work after host0 corrupted, so either test case is broken, or
658  this whole routine is not being called. */
660  service_name,
661  "SOCKSHOST",
662  &host0))
663  host0 = NULL;
665  (host0 != NULL) ? host0
666  : "127.0.0.1",
667  port0);
668  GNUNET_free_non_null (host0);
669 
670  /* Sets to NULL if they do not exist */
672  service_name,
673  "SOCKSUSER",
674  &user);
676  service_name,
677  "SOCKSPASS",
678  &pass);
679  ih = GNUNET_SOCKS_init_handshake (user, pass);
680  GNUNET_free_non_null (user);
681  GNUNET_free_non_null (pass);
682 
683  GNUNET_SOCKS_set_handshake_destination (ih, host1, port1);
684  GNUNET_free (host1);
685  return GNUNET_SOCKS_run_handshake (ih, socks5);
686 }
687 
688 
689 /* socks.c */
#define SOCKS5_AUTH_NOAUTH
Definition: socks.c:40
struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *hostname, uint16_t port)
Create a connection handle by (asynchronously) connecting to a host.
unsigned char outbuf[1024]
Precomputed SOCKS5 handshake ouput buffer.
Definition: socks.c:160
#define SOCKS5_REP_EXPIRED
Definition: socks.c:55
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
#define SOCKS5_REP_FAIL
Definition: socks.c:50
#define SOCKS5_REP_NALLOWED
Definition: socks.c:51
#define GNUNET_TIME_UNIT_MINUTES
One minute.
void GNUNET_CONNECTION_acivate_proxied(struct GNUNET_CONNECTION_Handle *proxied)
Activate proxied connection and destroy initial proxy handshake connection.
#define SOCKS5_step_done
Definition: socks.c:130
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
unsigned char * inend
Definition: socks.c:176
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static struct Experiment * e
#define SOCKS5_AUTH_USERPASS
Definition: socks.c:42
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define SOCKS5_REP_REFUSED
Definition: socks.c:54
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define SOCKS5_step_cmd
Definition: socks.c:129
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
static struct LoggingHandle * l
#define SOCKS5_REP_NUNREACH
Definition: socks.c:52
#define register_reciever_wants(ih)
Definition: socks.c:188
#define SOCKS5_step_greet
Definition: socks.c:127
struct GNUNET_SOCKS_Handshake * GNUNET_SOCKS_init_handshake_noauth()
Initialize a SOCKS5 handshake without authentication, thereby possibly sharing a Tor circuit with ano...
Definition: socks.c:508
struct GNUNET_CONNECTION_TransmitHandle * register_sender(struct GNUNET_SOCKS_Handshake *ih)
Register SOCKS5 handshake sender.
Definition: socks.c:429
void GNUNET_SOCKS_set_handshake_destination(struct GNUNET_SOCKS_Handshake *ih, const char *host, uint16_t port)
Build request that the SOCKS5 proxy open a TCP/IP stream to the given host and port.
Definition: socks.c:523
struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_minute_(void)
Return relative time of 1 minute.
Definition: time.c:195
int GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
struct GNUNET_CONNECTION_Handle * GNUNET_SOCKS_do_connect(const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg)
Try to connect to a service configured to use a SOCKS5 proxy.
Definition: socks.c:610
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:51
static char buf[2048]
int GNUNET_CONNECTION_receive(struct GNUNET_CONNECTION_Handle *connection, size_t max, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_Receiver receiver, void *receiver_cls)
Receive data from the given connection.
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:442
struct GNUNET_CONNECTION_Handle * target_connection
Connection handle initially returned to client.
Definition: socks.c:145
void SOCKS5_handshake_done(struct GNUNET_SOCKS_Handshake *ih)
Conclude the SOCKS5 handshake successfully.
Definition: socks.c:203
int step
Our stage in the SOCKS5 handshake.
Definition: socks.c:155
#define SOCKS5_REP_ANOTSUP
Definition: socks.c:57
void SOCKS5_handshake_step(struct GNUNET_SOCKS_Handshake *ih)
Read one step in the SOCKS5 handshake.
Definition: socks.c:215
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
static unsigned int size
Size of the "table".
Definition: peer.c:67
unsigned char * outstep[4]
Pointers delineating protoocol steps in the outbut buffer.
Definition: socks.c:165
int GNUNET_SOCKS_check_service(const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg)
Check if a SOCKS proxy is required by a service.
Definition: socks.c:593
void register_reciever(struct GNUNET_SOCKS_Handshake *ih, int want)
Register callback to read from the SOCKS5 proxy.
Definition: socks.c:353
#define LOG(kind,...)
Definition: socks.c:32
const char * SOCKS5_REP_names(int rep)
Definition: socks.c:61
#define SOCKS5_REP_SUCCEEDED
Definition: socks.c:49
unsigned char * SOCK5_proto_string(unsigned char *b, const char *s)
Encode a string for the SOCKS5 protocol by prefixing it a byte stating its length and stripping the t...
Definition: socks.c:111
unsigned char inbuf[1024]
SOCKS5 handshake input buffer.
Definition: socks.c:170
struct GNUNET_CONNECTION_TransmitHandle * th
Transmission handle on socks5_connection.
Definition: socks.c:150
static uint16_t port
Port number.
Definition: gnunet-bcd.c:81
size_t transmit_ready(void *cls, size_t size, void *buf)
Register SOCKS5 handshake sender.
Definition: socks.c:372
configuration data
Definition: configuration.c:85
struct GNUNET_CONNECTION_TransmitHandle * GNUNET_CONNECTION_notify_transmit_ready(struct GNUNET_CONNECTION_Handle *connection, size_t size, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls)
Ask the connection to call us once the specified number of bytes are free in the transmission buffer...
#define SOCKS5_AUTH_REJECT
Definition: socks.c:39
unsigned char * instart
Pointers delimiting the current step in the input buffer.
Definition: socks.c:175
struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_proxied_from_handshake(struct GNUNET_CONNECTION_Handle *cph)
Create a connection to be proxied using a given connection.
struct GNUNET_CONNECTION_Handle * GNUNET_SOCKS_run_handshake(struct GNUNET_SOCKS_Handshake *ih, struct GNUNET_CONNECTION_Handle *c)
Run a SOCKS5 handshake on an open but unused TCP connection.
Definition: socks.c:573
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_CONNECTION_Handle * socks5_connection
Connection handle used for SOCKS5.
Definition: socks.c:140
#define SOCKS5_REP_HUNREACH
Definition: socks.c:53
State of the SOCKS5 handshake.
Definition: socks.c:135
handle for a network connection
#define SOCKS5_step_auth
Definition: socks.c:128
#define SOCKS5_REP_INVADDR
Definition: socks.c:58
void reciever(void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode)
Callback to read from the SOCKS5 proxy.
Definition: socks.c:329
#define SOCKS5_REP_CNOTSUP
Definition: socks.c:56
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
struct GNUNET_SOCKS_Handshake * GNUNET_SOCKS_init_handshake(const char *user, const char *pass)
Initialize a SOCKS5 handshake for authentication via username and password.
Definition: socks.c:459