glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / util / socks.c
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
16 /**
17  * @file util/socks.c
18  * @brief  SOCKS5 connection support
19  * @author Jeffrey Burdges
20  *
21  * These routines should be called only on newly active connections.
22  */
23 #include "platform.h"
24 #include "gnunet_util_lib.h"
25
26
27 #define LOG(kind,...) GNUNET_log_from (kind, "util-socks", __VA_ARGS__)
28
29 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-socks", syscall)
30
31
32 /* SOCKS5 authentication methods */
33 #define SOCKS5_AUTH_REJECT 0xFF /* No acceptable auth method */
34 #define SOCKS5_AUTH_NOAUTH 0x00 /* without authentication */
35 #define SOCKS5_AUTH_GSSAPI 0x01 /* GSSAPI */
36 #define SOCKS5_AUTH_USERPASS 0x02 /* User/Password */
37 #define SOCKS5_AUTH_CHAP 0x03 /* Challenge-Handshake Auth Proto. */
38 #define SOCKS5_AUTH_EAP 0x05 /* Extensible Authentication Proto. */
39 #define SOCKS5_AUTH_MAF 0x08 /* Multi-Authentication Framework */
40
41
42 /* SOCKS5 connection responces */
43 #define SOCKS5_REP_SUCCEEDED 0x00 /* succeeded */
44 #define SOCKS5_REP_FAIL 0x01 /* general SOCKS serer failure */
45 #define SOCKS5_REP_NALLOWED 0x02 /* connection not allowed by ruleset */
46 #define SOCKS5_REP_NUNREACH 0x03 /* Network unreachable */
47 #define SOCKS5_REP_HUNREACH 0x04 /* Host unreachable */
48 #define SOCKS5_REP_REFUSED 0x05 /* connection refused */
49 #define SOCKS5_REP_EXPIRED 0x06 /* TTL expired */
50 #define SOCKS5_REP_CNOTSUP 0x07 /* Command not supported */
51 #define SOCKS5_REP_ANOTSUP 0x08 /* Address not supported */
52 #define SOCKS5_REP_INVADDR 0x09 /* Inalid address */
53
54 const char * SOCKS5_REP_names(int rep)
55 {
56   switch (rep) {
57     case SOCKS5_REP_SUCCEEDED: return "succeeded";
58     case SOCKS5_REP_FAIL: return "general SOCKS server failure";
59     case SOCKS5_REP_NALLOWED: return "connection not allowed by ruleset";
60     case SOCKS5_REP_NUNREACH: return "Network unreachable";
61     case SOCKS5_REP_HUNREACH: return "Host unreachable";
62     case SOCKS5_REP_REFUSED: return "connection refused";
63     case SOCKS5_REP_EXPIRED: return "TTL expired";
64     case SOCKS5_REP_CNOTSUP: return "Command not supported";
65     case SOCKS5_REP_ANOTSUP: return "Address not supported";
66     case SOCKS5_REP_INVADDR: return "Invalid address";
67     default: return NULL;
68   }
69 };
70
71
72 /**
73  * Encode a string for the SOCKS5 protocol by prefixing it a byte stating its
74  * length and stipping the trailing zero byte.  Truncates any string longer
75  * than 255 bytes.
76  *
77  * @param b buffer to contain the encoded string
78  * @param s string to encode
79  * @return pointer to the end of the encoded string in the buffer
80  */
81 unsigned char *
82 SOCK5_proto_string(unsigned char * b,
83                    const char * s)
84 {
85   size_t l = strlen(s);
86
87   if (l > 255)
88   {
89     LOG (GNUNET_ERROR_TYPE_WARNING,
90          "SOCKS5 cannot handle hostnames, usernames, or passwords over 255 bytes, truncating.\n");
91     l=255;
92   }
93   *(b++) = (unsigned char) l;
94   strncpy ((char *)b, s, l);
95   return b+l;
96 }
97
98
99 #define SOCKS5_step_greet 0
100 #define SOCKS5_step_auth  1
101 #define SOCKS5_step_cmd   2
102 #define SOCKS5_step_done  3
103
104 /**
105  * State of the SOCKS5 handshake.
106  */
107 struct GNUNET_SOCKS_Handshake
108 {
109
110   /**
111    * Connection handle used for SOCKS5
112    */
113   struct GNUNET_CONNECTION_Handle *socks5_connection;
114
115   /**
116    * Connection handle initially returned to client
117    */
118   struct GNUNET_CONNECTION_Handle *target_connection;
119
120   /**
121    * Transmission handle on socks5_connection.
122    */
123   struct GNUNET_CONNECTION_TransmitHandle *th;
124
125   /**
126    * Our stage in the SOCKS5 handshake
127    */
128   int step;
129
130   /**
131    * Precomputed SOCKS5 handshake ouput buffer
132    */
133   unsigned char outbuf[1024];
134
135   /**
136    * Pointers delineating protoocol steps in the outbut buffer
137    */
138   unsigned char * (outstep[4]);
139
140   /**
141    * SOCKS5 handshake input buffer
142    */
143   unsigned char inbuf[1024];
144
145   /**
146    * Pointers delimiting the current step in the input buffer
147    */
148   unsigned char * instart;
149   unsigned char * inend;
150 };
151
152
153 /* Regitering prototypes */
154
155 void
156 register_reciever (struct GNUNET_SOCKS_Handshake *ih, int want);
157
158   /* In fact, the client sends first rule in GNUNet suggests one could take
159    * large mac read sizes without fear of screwing up the proxied protocol,
160    * but we make a proper SOCKS5 client. */
161 #define register_reciever_wants(ih) ((SOCKS5_step_cmd == ih->step) ? 10 : 2)
162
163
164 struct GNUNET_CONNECTION_TransmitHandle *
165 register_sender (struct GNUNET_SOCKS_Handshake *ih);
166
167
168 /**
169  * Conclude the SOCKS5 handshake successfully.
170  *
171  * @param ih SOCKS5 handshake, consumed here.
172  * @param c open unused connection, consumed here.
173  * @return Connection handle that becomes usable when the handshake completes.
174  */
175 void
176 SOCKS5_handshake_done(struct GNUNET_SOCKS_Handshake *ih)
177 {
178   GNUNET_CONNECTION_acivate_proxied (ih->target_connection);
179 }
180
181
182 /**
183  * Read one step in the SOCKS5 handshake.
184  *
185  * @param ih SOCKS5 Handshake
186  */
187 void
188 SOCKS5_handshake_step (struct GNUNET_SOCKS_Handshake *ih)
189 {
190   unsigned char * b = ih->instart;
191   size_t available = ih->inend - b;
192
193   int want = register_reciever_wants(ih);
194   if (available < want) {
195     register_reciever (ih, want - available);
196     return;
197   }
198   GNUNET_assert (SOCKS5_step_done > ih->step && ih->step >= 0);
199   switch (ih->step) {
200     case SOCKS5_step_greet:  /* SOCKS5 server's greeting */
201       if (b[0] != 5)
202       {
203         LOG (GNUNET_ERROR_TYPE_ERROR,
204              "Not a SOCKS5 server\n");
205         GNUNET_assert (0);
206       }
207       switch (b[1]) {
208         case SOCKS5_AUTH_NOAUTH:
209           ih->step=SOCKS5_step_cmd;  /* no authentication to do */
210           break;
211         case SOCKS5_AUTH_USERPASS:
212           ih->step=SOCKS5_step_auth;
213           break;
214         case SOCKS5_AUTH_REJECT:
215           LOG (GNUNET_ERROR_TYPE_ERROR,
216                "No authentication method accepted\n");
217           return;
218         default:
219           LOG (GNUNET_ERROR_TYPE_ERROR,
220                "Not a SOCKS5 server / Nonsensical authentication\n");
221           return;
222       }
223       b += 2;
224       break;
225     case SOCKS5_step_auth:  /* SOCKS5 server's responce to authentication */
226       if (b[1] != 0)
227       {
228         LOG (GNUNET_ERROR_TYPE_ERROR,
229              "SOCKS5 authentication failed\n");
230         GNUNET_assert (0);
231       }
232       ih->step=SOCKS5_step_cmd;
233       b += 2;
234       break;
235     case SOCKS5_step_cmd:  /* SOCKS5 server's responce to command */
236       if (b[0] != 5)
237       {
238         LOG (GNUNET_ERROR_TYPE_ERROR,
239              "SOCKS5 protocol error\n");
240         GNUNET_assert (0);
241       }
242       if (0 != b[1]) {
243         LOG (GNUNET_ERROR_TYPE_ERROR,
244              "SOCKS5 connection error : %s\n",
245              SOCKS5_REP_names(b[1]));
246         return;
247       }
248       b += 3;
249       /* There is no reason to verify host and port afaik. */
250       switch (*(b++)) {
251         case 1: /* IPv4 */
252           b += sizeof(struct in_addr);  /* 4 */
253           break;
254         case 4: /* IPv6 */
255           b += sizeof(struct in6_addr);  /* 16 */
256           break;
257         case 3: /* hostname */
258           b += *b;
259           break;
260       }
261       b += 2;  /* port */
262       if (b > ih->inend) {
263         register_reciever (ih, b - ih->inend);
264         return;
265       }
266       ih->step = SOCKS5_step_done;
267       LOG (GNUNET_ERROR_TYPE_DEBUG,
268            "SOCKS5 server : %s\n",
269            SOCKS5_REP_names(b[1]));
270       ih->instart = b;
271       SOCKS5_handshake_done (ih);
272       return;
273     case SOCKS5_step_done:
274       GNUNET_assert (0);
275   }
276   ih->instart = b;
277   /* Do not reschedule the sender unless we're done reading.
278    * I imagine this lets us avoid ever cancelling the transmit handle. */
279   register_sender (ih);
280 }
281
282
283 /**
284  * Callback to read from the SOCKS5 proxy.
285  *
286  * @param client the service
287  * @param handler function to call with the message
288  * @param handler_cls closure for @a handler
289  */
290 void
291 reciever (void *cls,
292           const void *buf, size_t available,
293           const struct sockaddr * addr,
294           socklen_t addrlen, int errCode)
295 {
296   struct GNUNET_SOCKS_Handshake * ih = cls;
297   GNUNET_assert (&ih->inend[available] < &ih->inbuf[1024]);
298   GNUNET_memcpy(ih->inend, buf, available);
299   ih->inend += available;
300   SOCKS5_handshake_step (ih);
301 }
302
303
304 /**
305  * Register callback to read from the SOCKS5 proxy.
306  *
307  * @param client the service
308  * @param handler function to call with the message
309  * @param handler_cls closure for @a handler
310  */
311 void
312 register_reciever (struct GNUNET_SOCKS_Handshake *ih, int want)
313 {
314   GNUNET_CONNECTION_receive (ih->socks5_connection,
315                              want,
316                              GNUNET_TIME_relative_get_minute_ (),
317                              &reciever,
318                              ih);
319 }
320
321
322 /**
323  * Register SOCKS5 handshake sender
324  *
325  * @param cls closure (SOCKS handshake)
326  * @param size number of bytes available in @a buf
327  * @param buf where the callee should write the message
328  * @return number of bytes written to @a buf
329  */
330 size_t
331 transmit_ready (void *cls,
332                 size_t size,
333                 void *buf)
334 {
335   struct GNUNET_SOCKS_Handshake * ih = cls;
336
337   /* connection.c has many routines that call us with buf == NULL :
338    * signal_transmit_error() - DNS, etc. active
339    *   connect_fail_continuation()
340    *     connect_probe_continuation() - timeout
341    *     try_connect_using_address() - DNS failure/timeout
342    *     transmit_timeout() - retry failed?
343    * GNUNET_CONNECTION_notify_transmit_ready() can schedule :
344    *   transmit_timeout() - DNS still working
345    *   connect_error() - DNS done but no socket?
346    * transmit_ready() - scheduler shutdown or timeout, or signal_transmit_error()
347    * We'd need to dig into the scheduler to guess at the reason, as
348    * connection.c tells us nothing itself, but mostly its timouts.
349    * Initially, we'll simply ignore this and leave massive timeouts, but
350    * maybe that should change for error handling pruposes.  It appears that
351    * successful operations, including DNS resolution, do not use this.  */
352   if (NULL == buf)
353   {
354     if (0 == ih->step)
355     {
356       LOG (GNUNET_ERROR_TYPE_WARNING,
357            "Timeout contacting SOCKS server, retrying indefinitely, but probably hopeless.\n");
358       register_sender (ih);
359     }
360     else
361     {
362       LOG (GNUNET_ERROR_TYPE_ERROR,
363            "Timeout during mid SOCKS handshake (step %u), probably not a SOCKS server.\n",
364            ih->step);
365       GNUNET_break (0);
366     }
367     return 0;
368   }
369
370   GNUNET_assert ( (1024 >= size) && (size > 0) );
371   GNUNET_assert ( (SOCKS5_step_done > ih->step) && (ih->step >= 0) );
372   unsigned char * b = ih->outstep[ih->step];
373   unsigned char * e = ih->outstep[ih->step+1];
374   GNUNET_assert (e <= &ih->outbuf[1024]);
375   unsigned int l = e - b;
376   GNUNET_assert (size >= l);
377   GNUNET_memcpy (buf,
378                  b,
379                  l);
380   register_reciever (ih,
381                      register_reciever_wants (ih));
382   return l;
383 }
384
385
386 /**
387  * Register SOCKS5 handshake sender
388  *
389  * @param ih handshake
390  * @return non-NULL if the notify callback was queued,
391  *         NULL if we are already going to notify someone else (busy)
392  */
393 struct GNUNET_CONNECTION_TransmitHandle *
394 register_sender (struct GNUNET_SOCKS_Handshake *ih)
395 {
396   struct GNUNET_TIME_Relative timeout = GNUNET_TIME_UNIT_MINUTES;
397
398   GNUNET_assert (SOCKS5_step_done > ih->step);
399   GNUNET_assert (ih->step >= 0);
400   if (0 == ih->step)
401     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3);
402   unsigned char * b = ih->outstep[ih->step];
403   unsigned char * e = ih->outstep[ih->step+1];
404   GNUNET_assert (ih->outbuf <= b && b < e && e < &ih->outbuf[1024]);
405   ih->th = GNUNET_CONNECTION_notify_transmit_ready (ih->socks5_connection,
406                                                     e - b,
407                                                     timeout,
408                                                     &transmit_ready,
409                                                     ih);
410   return ih->th;
411 }
412
413
414 /**
415  * Initialize a SOCKS5 handshake for authentication via username and
416  * password.  Tor uses SOCKS username and password authentication to assign
417  * programs unique circuits.
418  *
419  * @param user username for the proxy
420  * @param pass password for the proxy
421  * @return Valid SOCKS5 hanbdshake handle
422  */
423 struct GNUNET_SOCKS_Handshake *
424 GNUNET_SOCKS_init_handshake (const char *user, const char *pass)
425 {
426   struct GNUNET_SOCKS_Handshake *ih = GNUNET_new (struct GNUNET_SOCKS_Handshake);
427   unsigned char * b = ih->outbuf;
428
429   ih->outstep[SOCKS5_step_greet] = b;
430   *(b++) = 5; /* SOCKS5 */
431   unsigned char * n = b++;
432   *n = 1; /* Number of authentication methods */
433   /* We support no authentication even when requesting authentication,
434    * but this appears harmless, given the way that Tor uses authentication.
435    * And some SOCKS5 servers might require this.  */
436   *(b++) = SOCKS5_AUTH_NOAUTH;
437   if (NULL != user) {
438     *(b++) = SOCKS5_AUTH_USERPASS;
439     (*n)++;
440   }
441   /* There is no apperent reason to support authentication methods beyond
442    * username and password since afaik Tor does not support them. */
443
444   /* We authenticate with an empty username and password if the server demands
445    * them but we do not have any. */
446   if (user == NULL)
447     user = "";
448   if (pass == NULL)
449     pass = "";
450
451   ih->outstep[SOCKS5_step_auth] = b;
452   *(b++) = 1; /* subnegotiation ver.: 1 */
453   b = SOCK5_proto_string(b,user);
454   b = SOCK5_proto_string(b,pass);
455
456   ih->outstep[SOCKS5_step_cmd] = b;
457
458   ih->inend = ih->instart = ih->inbuf;
459
460   return ih;
461 }
462
463
464 /**
465  * Initialize a SOCKS5 handshake without authentication, thereby possibly
466  * sharing a Tor circuit with another process.
467  *
468  * @return Valid SOCKS5 hanbdshake handle
469  */
470 struct GNUNET_SOCKS_Handshake *
471 GNUNET_SOCKS_init_handshake_noauth ()
472 {
473   return GNUNET_SOCKS_init_handshake (NULL,NULL);
474 }
475
476
477 /**
478  * Build request that the SOCKS5 proxy open a TCP/IP stream to the given host
479  * and port.
480  *
481  * @param ih SOCKS5 handshake
482  * @param hostname
483  * @param port
484  */
485 void
486 GNUNET_SOCKS_set_handshake_destination (struct GNUNET_SOCKS_Handshake *ih,
487                                          const char *host, uint16_t port)
488 {
489   union {
490     struct in_addr in4;
491     struct in6_addr in6;
492   } ia;
493   unsigned char * b = ih->outstep[SOCKS5_step_cmd];
494
495   *(b++) = 5;  /* SOCKS5 */
496   *(b++) = 1;  /* Establish a TCP/IP stream */
497   *(b++) = 0;  /* reserved */
498
499   /* Specify destination */
500   if (1 == inet_pton(AF_INET,host,&ia.in4)) {
501     *(b++)= 1;  /* IPv4 */
502     GNUNET_memcpy (b, &ia.in4, sizeof(struct in_addr));
503     b += sizeof(struct in_addr);  /* 4 */
504   } else if (1 == inet_pton(AF_INET6,host,&ia.in6)) {
505     *(b++)= 4;  /* IPv6 */
506     GNUNET_memcpy (b, &ia.in6, sizeof(struct in6_addr));
507     b += sizeof(struct in6_addr);  /* 16 */
508   } else {
509     *(b++)= 3;  /* hostname */
510     b = SOCK5_proto_string (b, host);
511   }
512
513   /* Specify port */
514   *(uint16_t*)b = htons (port);
515   b += 2;
516
517   ih->outstep[SOCKS5_step_done] = b;
518 }
519
520
521 /**
522  * Run a SOCKS5 handshake on an open but unused TCP connection.
523  *
524  * @param ih SOCKS5 handshake, consumed here.
525  * @param c open unused connection, consumed here.
526  * @return Connection handle that becomes usable when the SOCKS5 handshake completes.
527  */
528 struct GNUNET_CONNECTION_Handle *
529 GNUNET_SOCKS_run_handshake(struct GNUNET_SOCKS_Handshake *ih,
530                             struct GNUNET_CONNECTION_Handle *c)
531 {
532   ih->socks5_connection=c;
533   ih->target_connection = GNUNET_CONNECTION_create_proxied_from_handshake (c);
534   register_sender (ih);
535
536   return ih->target_connection;
537 }
538
539
540 /**
541  * Check if a SOCKS proxy is required by a service.  Do not use local service
542  * if a SOCKS proxy port is configured as this could deanonymize a user.
543  *
544  * @param service_name name of service to connect to
545  * @param cfg configuration to use
546  * @return GNUNET_YES if so, GNUNET_NO if not
547  */
548 int
549 GNUNET_SOCKS_check_service (const char *service_name,
550                             const struct GNUNET_CONFIGURATION_Handle *cfg)
551 {
552   return GNUNET_CONFIGURATION_have_value (cfg, service_name, "SOCKSPORT") ||
553          GNUNET_CONFIGURATION_have_value (cfg, service_name, "SOCKSHOST");
554 }
555
556
557 /**
558  * Try to connect to a service configured to use a SOCKS5 proxy.
559  *
560  * @param service_name name of service to connect to
561  * @param cfg configuration to use
562  * @return Connection handle that becomes usable when the handshake completes.
563  *         NULL if SOCKS not configured or not configured properly
564  */
565 struct GNUNET_CONNECTION_Handle *
566 GNUNET_SOCKS_do_connect (const char *service_name,
567                          const struct GNUNET_CONFIGURATION_Handle *cfg)
568 {
569   struct GNUNET_SOCKS_Handshake *ih;
570   struct GNUNET_CONNECTION_Handle *socks5; /* *proxied */
571   char *host0;
572   char *host1;
573   char *user;
574   char *pass;
575   unsigned long long port0;
576   unsigned long long port1;
577
578   if (GNUNET_YES !=
579       GNUNET_SOCKS_check_service (service_name, cfg))
580     return NULL;
581   if (GNUNET_OK !=
582       GNUNET_CONFIGURATION_get_value_number (cfg,
583                                              service_name,
584                                              "SOCKSPORT",
585                                              &port0))
586     port0 = 9050;
587   /* A typical Tor client should usually try port 9150 for the TBB too, but
588    * GNUnet can probably assume a system Tor installation. */
589   if (port0 > 65535 || port0 <= 0)
590   {
591     LOG (GNUNET_ERROR_TYPE_WARNING,
592          _("Attempting to use invalid port %d as SOCKS proxy for service `%s'.\n"),
593          port0,
594          service_name);
595     return NULL;
596   }
597   if ( (GNUNET_OK !=
598         GNUNET_CONFIGURATION_get_value_number (cfg,
599                                                service_name,
600                                                "PORT",
601                                                &port1)) ||
602        (port1 > 65535) ||
603        (port1 <= 0) ||
604        (GNUNET_OK !=
605         GNUNET_CONFIGURATION_get_value_string (cfg,
606                                                service_name,
607                                                "HOSTNAME",
608                                                &host1)))
609   {
610     LOG (GNUNET_ERROR_TYPE_WARNING,
611          _("Attempting to proxy service `%s' to invalid port %d or hostname.\n"),
612          service_name,
613          port1);
614     return NULL;
615   }
616   /* Appeared to still work after host0 corrupted, so either test case is broken, or
617      this whole routine is not being called. */
618   if (GNUNET_OK !=
619       GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "SOCKSHOST", &host0))
620     host0 = NULL;
621   socks5 = GNUNET_CONNECTION_create_from_connect (cfg,
622                                                   (host0 != NULL)
623                                                   ? host0
624                                                   :"127.0.0.1",
625                                                   port0);
626   GNUNET_free_non_null (host0);
627
628   /* Sets to NULL if they do not exist */
629   (void) GNUNET_CONFIGURATION_get_value_string (cfg,
630                                                 service_name,
631                                                 "SOCKSUSER",
632                                                 &user);
633   (void) GNUNET_CONFIGURATION_get_value_string (cfg,
634                                                 service_name,
635                                                 "SOCKSPASS",
636                                                 &pass);
637   ih = GNUNET_SOCKS_init_handshake(user,pass);
638   GNUNET_free_non_null (user);
639   GNUNET_free_non_null (pass);
640
641   GNUNET_SOCKS_set_handshake_destination (ih,
642                                           host1,
643                                           port1);
644   GNUNET_free (host1);
645   return GNUNET_SOCKS_run_handshake (ih,
646                                      socks5);
647 }
648
649 /* socks.c */