]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - proxy.c
Initialise some members of the Proxy_Socket structure that were left
[PuTTY.git] / proxy.c
1 /*
2  * Network proxy abstraction in PuTTY
3  *
4  * A proxy layer, if necessary, wedges itself between the network
5  * code and the higher level backend.
6  */
7
8 #include <windows.h>
9
10 #include <assert.h>
11
12 #define DEFINE_PLUG_METHOD_MACROS
13 #include "putty.h"
14 #include "network.h"
15 #include "proxy.h"
16
17 /*
18  * Call this when proxy negotiation is complete, so that this
19  * socket can begin working normally.
20  */
21 void proxy_activate (Proxy_Socket p)
22 {
23     void *data;
24     int len;
25
26     p->state = PROXY_STATE_ACTIVE;
27
28     /* let's try to keep extra receive events from coming through */
29     sk_set_frozen(p->sub_socket, 1);
30
31     /* send buffered OOB writes */
32     while (bufchain_size(&p->pending_oob_output_data) > 0) {
33         bufchain_prefix(&p->pending_oob_output_data, &data, &len);
34         sk_write_oob(p->sub_socket, data, len);
35         bufchain_consume(&p->pending_oob_output_data, len);
36     }
37     bufchain_clear(&p->pending_oob_output_data);
38
39     /* send buffered normal writes */
40     while (bufchain_size(&p->pending_output_data) > 0) {
41         bufchain_prefix(&p->pending_output_data, &data, &len);
42         sk_write(p->sub_socket, data, len);
43         bufchain_consume(&p->pending_output_data, len);
44     }
45     bufchain_clear(&p->pending_output_data);
46
47     /* if we were asked to flush the output during
48      * the proxy negotiation process, do so now.
49      */
50     if (p->pending_flush) sk_flush(p->sub_socket);
51
52     /* forward buffered recv data to the backend */
53     while (bufchain_size(&p->pending_input_data) > 0) {
54         bufchain_prefix(&p->pending_input_data, &data, &len);
55         plug_receive(p->plug, 0, data, len);
56         bufchain_consume(&p->pending_input_data, len);
57     }
58     bufchain_clear(&p->pending_input_data);
59
60     /* now set the underlying socket to whatever freeze state they wanted */
61     sk_set_frozen(p->sub_socket, p->freeze);
62 }
63
64 /* basic proxy socket functions */
65
66 static Plug sk_proxy_plug (Socket s, Plug p)
67 {
68     Proxy_Socket ps = (Proxy_Socket) s;
69     Plug ret = ps->plug;
70     if (p)
71         ps->plug = p;
72     return ret;
73 }
74
75 static void sk_proxy_close (Socket s)
76 {
77     Proxy_Socket ps = (Proxy_Socket) s;
78
79     sk_close(ps->sub_socket);
80     sfree(ps);
81 }
82
83 static int sk_proxy_write (Socket s, char *data, int len)
84 {
85     Proxy_Socket ps = (Proxy_Socket) s;
86
87     if (ps->state != PROXY_STATE_ACTIVE) {
88         bufchain_add(&ps->pending_output_data, data, len);
89         return bufchain_size(&ps->pending_output_data);
90     }
91     return sk_write(ps->sub_socket, data, len);
92 }
93
94 static int sk_proxy_write_oob (Socket s, char *data, int len)
95 {
96     Proxy_Socket ps = (Proxy_Socket) s;
97
98     if (ps->state != PROXY_STATE_ACTIVE) {
99         bufchain_clear(&ps->pending_output_data);
100         bufchain_clear(&ps->pending_oob_output_data);
101         bufchain_add(&ps->pending_oob_output_data, data, len);
102         return len;
103     }
104     return sk_write_oob(ps->sub_socket, data, len);
105 }
106
107 static void sk_proxy_flush (Socket s)
108 {
109     Proxy_Socket ps = (Proxy_Socket) s;
110
111     if (ps->state != PROXY_STATE_ACTIVE) {
112         ps->pending_flush = 1;
113         return;
114     }
115     sk_flush(ps->sub_socket);
116 }
117
118 static void sk_proxy_set_private_ptr (Socket s, void *ptr)
119 {
120     Proxy_Socket ps = (Proxy_Socket) s;
121     sk_set_private_ptr(ps->sub_socket, ptr);
122 }
123
124 static void * sk_proxy_get_private_ptr (Socket s)
125 {
126     Proxy_Socket ps = (Proxy_Socket) s;
127     return sk_get_private_ptr(ps->sub_socket);
128 }
129
130 static void sk_proxy_set_frozen (Socket s, int is_frozen)
131 {
132     Proxy_Socket ps = (Proxy_Socket) s;
133
134     if (ps->state != PROXY_STATE_ACTIVE) {
135         ps->freeze = is_frozen;
136         return;
137     }
138     sk_set_frozen(ps->sub_socket, is_frozen);
139 }
140
141 static char * sk_proxy_socket_error (Socket s)
142 {
143     Proxy_Socket ps = (Proxy_Socket) s;
144     if (ps->error != NULL || ps->sub_socket == NULL) {
145         return ps->error;
146     }
147     return sk_socket_error(ps->sub_socket);
148 }
149
150 /* basic proxy plug functions */
151
152 static int plug_proxy_closing (Plug p, char *error_msg,
153                                int error_code, int calling_back)
154 {
155     Proxy_Plug pp = (Proxy_Plug) p;
156     Proxy_Socket ps = pp->proxy_socket;
157
158     if (ps->state != PROXY_STATE_ACTIVE) {
159         ps->closing_error_msg = error_msg;
160         ps->closing_error_code = error_code;
161         ps->closing_calling_back = calling_back;
162         return ps->negotiate(ps, PROXY_CHANGE_CLOSING);
163     }
164     return plug_closing(ps->plug, error_msg,
165                         error_code, calling_back);
166 }
167
168 static int plug_proxy_receive (Plug p, int urgent, char *data, int len)
169 {
170     Proxy_Plug pp = (Proxy_Plug) p;
171     Proxy_Socket ps = pp->proxy_socket;
172
173     if (ps->state != PROXY_STATE_ACTIVE) {
174         /* we will lose the urgentness of this data, but since most,
175          * if not all, of this data will be consumed by the negotiation
176          * process, hopefully it won't affect the protocol above us
177          */
178         bufchain_add(&ps->pending_input_data, data, len);
179         ps->receive_urgent = urgent;
180         ps->receive_data = data;
181         ps->receive_len = len;
182         return ps->negotiate(ps, PROXY_CHANGE_RECEIVE);
183     }
184     return plug_receive(ps->plug, urgent, data, len);
185 }
186
187 static void plug_proxy_sent (Plug p, int bufsize)
188 {
189     Proxy_Plug pp = (Proxy_Plug) p;
190     Proxy_Socket ps = pp->proxy_socket;
191
192     if (ps->state != PROXY_STATE_ACTIVE) {
193         ps->sent_bufsize = bufsize;
194         ps->negotiate(ps, PROXY_CHANGE_SENT);
195         return;
196     }
197     plug_sent(ps->plug, bufsize);
198 }
199
200 static int plug_proxy_accepting (Plug p, void *sock)
201 {
202     Proxy_Plug pp = (Proxy_Plug) p;
203     Proxy_Socket ps = pp->proxy_socket;
204
205     if (ps->state != PROXY_STATE_ACTIVE) {
206         ps->accepting_sock = sock;
207         return ps->negotiate(ps, PROXY_CHANGE_ACCEPTING);
208     }
209     return plug_accepting(ps->plug, sock);
210 }
211
212 static int proxy_for_destination (SockAddr addr, char * hostname, int port)
213 {
214     int s = 0, e = 0;
215     char hostip[64];
216     int hostip_len, hostname_len;
217     char * exclude_list;
218
219     /* we want a string representation of the IP address for comparisons */
220     sk_getaddr(addr, hostip, 64);
221
222     hostip_len = strlen(hostip);
223     hostname_len = strlen(hostname);
224
225     exclude_list = cfg.proxy_exclude_list;
226
227     /* now parse the exclude list, and see if either our IP
228      * or hostname matches anything in it.
229      */
230
231     while (exclude_list[s]) {
232         while (exclude_list[s] &&
233                (isspace(exclude_list[s]) ||
234                 exclude_list[s] == ',')) s++;
235
236         if (!exclude_list[s]) break;
237
238         e = s;
239
240         while (exclude_list[e] &&
241                (isalnum(exclude_list[e]) ||
242                 exclude_list[e] == '-' ||
243                 exclude_list[e] == '.' ||
244                 exclude_list[e] == '*')) e++;
245
246         if (exclude_list[s] == '*') {
247             /* wildcard at beginning of entry */
248
249             if (strnicmp(hostip + hostip_len - (e - s - 1),
250                          exclude_list + s + 1, e - s - 1) == 0 ||
251                 strnicmp(hostname + hostname_len - (e - s - 1),
252                          exclude_list + s + 1, e - s - 1) == 0)
253                 return 0; /* IP/hostname range excluded. do not use proxy. */
254
255         } else if (exclude_list[e-1] == '*') {
256             /* wildcard at end of entry */
257
258             if (strnicmp(hostip, exclude_list + s, e - s - 1) == 0 ||
259                 strnicmp(hostname, exclude_list + s, e - s - 1) == 0)
260                 return 0; /* IP/hostname range excluded. do not use proxy. */
261
262         } else {
263             /* no wildcard at either end, so let's try an absolute
264              * match (ie. a specific IP)
265              */
266
267             if (stricmp(hostip, exclude_list + s) == 0)
268                 return 0; /* IP/hostname excluded. do not use proxy. */
269             if (stricmp(hostname, exclude_list + s) == 0)
270                 return 0; /* IP/hostname excluded. do not use proxy. */
271         }
272
273         s = e;
274     }
275
276     /* no matches in the exclude list, so use the proxy */
277     return 1;
278 }
279
280 Socket new_connection(SockAddr addr, char *hostname,
281                       int port, int privport,
282                       int oobinline, int nodelay, Plug plug)
283 {
284     static struct socket_function_table socket_fn_table = {
285         sk_proxy_plug,
286         sk_proxy_close,
287         sk_proxy_write,
288         sk_proxy_write_oob,
289         sk_proxy_flush,
290         sk_proxy_set_private_ptr,
291         sk_proxy_get_private_ptr,
292         sk_proxy_set_frozen,
293         sk_proxy_socket_error
294     };
295
296     static struct plug_function_table plug_fn_table = {
297         plug_proxy_closing,
298         plug_proxy_receive,
299         plug_proxy_sent,
300         plug_proxy_accepting
301     };
302
303     if (cfg.proxy_type != PROXY_NONE &&
304         proxy_for_destination(addr, hostname, port))
305     {
306         Proxy_Socket ret;
307         Proxy_Plug pplug;
308         SockAddr proxy_addr;
309         char * proxy_canonical_name;
310
311         ret = smalloc(sizeof(struct Socket_proxy_tag));
312         ret->fn = &socket_fn_table;
313         ret->plug = plug;
314         ret->remote_addr = addr;
315         ret->remote_port = port;
316
317         /* XXX review these initialisations, and initialise other fields
318          * in Proxy_Socket structure */
319         ret->error = NULL;
320         ret->pending_flush = 0;
321         ret->freeze = 0;
322
323         bufchain_init(&ret->pending_input_data);
324         bufchain_init(&ret->pending_output_data);
325         bufchain_init(&ret->pending_oob_output_data);
326
327         ret->sub_socket = NULL;
328         ret->state = PROXY_STATE_NEW;
329
330         if (cfg.proxy_type == PROXY_HTTP) {
331             ret->negotiate = proxy_http_negotiate;
332         } else if (cfg.proxy_type == PROXY_SOCKS) {
333             if (cfg.proxy_socks_version == 4)
334                 ret->negotiate = proxy_socks4_negotiate;
335             else
336                 ret->negotiate = proxy_socks5_negotiate;
337         } else if (cfg.proxy_type == PROXY_TELNET) {
338             ret->negotiate = proxy_telnet_negotiate;
339         } else {
340             ret->error = "Proxy error: Unknown proxy method";
341             return (Socket) ret;
342         }
343
344         /* create the proxy plug to map calls from the actual
345          * socket into our proxy socket layer */
346         pplug = smalloc(sizeof(struct Plug_proxy_tag));
347         pplug->fn = &plug_fn_table;
348         pplug->proxy_socket = ret;
349
350         /* look-up proxy */
351         proxy_addr = sk_namelookup(cfg.proxy_host,
352                                    &proxy_canonical_name);
353         sfree(proxy_canonical_name);
354
355         /* create the actual socket we will be using,
356          * connected to our proxy server and port.
357          */
358         ret->sub_socket = sk_new(proxy_addr, cfg.proxy_port,
359                                  privport, oobinline,
360                                  nodelay, (Plug) pplug);
361         if (sk_socket_error(ret->sub_socket) != NULL)
362             return (Socket) ret;
363
364         sk_addr_free(proxy_addr);
365
366         /* start the proxy negotiation process... */
367         sk_set_frozen(ret->sub_socket, 0);
368         ret->negotiate(ret, PROXY_CHANGE_NEW);
369
370         return (Socket) ret;
371     }
372
373     /* no proxy, so just return the direct socket */
374     return sk_new(addr, port, privport, oobinline, nodelay, plug);
375 }
376
377 Socket new_listener(int port, Plug plug, int local_host_only)
378 {
379     /* TODO: SOCKS (and potentially others) support inbound
380      * TODO: connections via the proxy. support them.
381      */
382
383     return sk_newlistener(port, plug, local_host_only);
384 }
385
386 /* ----------------------------------------------------------------------
387  * HTTP CONNECT proxy type.
388  */
389
390 static int get_line_end (char * data, int len)
391 {
392     int off = 0;
393
394     while (off < len)
395     {
396         if (data[off] == '\n') {
397             /* we have a newline */
398             off++;
399
400             /* is that the only thing on this line? */
401             if (off <= 2) return off;
402
403             /* if not, then there is the possibility that this header
404              * continues onto the next line, if it starts with a space
405              * or a tab.
406              */
407
408             if (off + 1 < len &&
409                 data[off+1] != ' ' &&
410                 data[off+1] != '\t') return off;
411
412             /* the line does continue, so we have to keep going
413              * until we see an the header's "real" end of line.
414              */
415             off++;
416         }
417
418         off++;
419     }
420
421     return -1;
422 }
423
424 int proxy_http_negotiate (Proxy_Socket p, int change)
425 {
426     if (p->state == PROXY_STATE_NEW) {
427         /* we are just beginning the proxy negotiate process,
428          * so we'll send off the initial bits of the request.
429          * for this proxy method, it's just a simple HTTP
430          * request
431          */
432         char buf[256], dest[64];
433
434         sk_getaddr(p->remote_addr, dest, 64);
435
436         sprintf(buf, "CONNECT %s:%i HTTP/1.1\r\nHost: %s:%i\r\n",
437                 dest, p->remote_port, dest, p->remote_port);
438         sk_write(p->sub_socket, buf, strlen(buf));
439
440         if (cfg.proxy_username[0] || cfg.proxy_password[0]) {
441             char buf[sizeof(cfg.proxy_username)+sizeof(cfg.proxy_password)];
442             char buf2[sizeof(buf)*4/3 + 100];
443             int i, j, len;
444             sprintf(buf, "%s:%s", cfg.proxy_username, cfg.proxy_password);
445             len = strlen(buf);
446             sprintf(buf2, "Proxy-Authorization: basic ");
447             for (i = 0, j = strlen(buf2); i < len; i += 3, j += 4)
448                 base64_encode_atom(buf+i, (len-i > 3 ? 3 : len-i), buf2+j);
449             strcpy(buf2+j, "\r\n");
450             sk_write(p->sub_socket, buf2, strlen(buf2));
451         }
452
453         sprintf(buf, "\r\n");
454         sk_write(p->sub_socket, buf, strlen(buf));
455
456         p->state = 1;
457         return 0;
458     }
459
460     if (change == PROXY_CHANGE_CLOSING) {
461         /* if our proxy negotiation process involves closing and opening
462          * new sockets, then we would want to intercept this closing
463          * callback when we were expecting it. if we aren't anticipating
464          * a socket close, then some error must have occurred. we'll
465          * just pass those errors up to the backend.
466          */
467         return plug_closing(p->plug, p->closing_error_msg,
468                             p->closing_error_code,
469                             p->closing_calling_back);
470     }
471
472     if (change == PROXY_CHANGE_SENT) {
473         /* some (or all) of what we wrote to the proxy was sent.
474          * we don't do anything new, however, until we receive the
475          * proxy's response. we might want to set a timer so we can
476          * timeout the proxy negotiation after a while...
477          */
478         return 0;
479     }
480
481     if (change == PROXY_CHANGE_ACCEPTING) {
482         /* we should _never_ see this, as we are using our socket to
483          * connect to a proxy, not accepting inbound connections.
484          * what should we do? close the socket with an appropriate
485          * error message?
486          */
487         return plug_accepting(p->plug, p->accepting_sock);
488     }
489
490     if (change == PROXY_CHANGE_RECEIVE) {
491         /* we have received data from the underlying socket, which
492          * we'll need to parse, process, and respond to appropriately.
493          */
494
495         char *data, *datap;
496         int len;
497         int eol;
498
499         if (p->state == 1) {
500
501             int min_ver, maj_ver, status;
502
503             /* get the status line */
504             len = bufchain_size(&p->pending_input_data);
505             assert(len > 0);           /* or we wouldn't be here */
506             data = smalloc(len);
507             bufchain_fetch(&p->pending_input_data, data, len);
508
509             eol = get_line_end(data, len);
510             if (eol < 0) {
511                 sfree(data);
512                 return 1;
513             }
514
515             status = -1;
516             /* We can't rely on whether the %n incremented the sscanf return */
517             if (sscanf((char *)data, "HTTP/%i.%i %n",
518                        &maj_ver, &min_ver, &status) < 2 || status == -1) {
519                 plug_closing(p->plug, "Proxy error: HTTP response was absent",
520                              PROXY_ERROR_GENERAL, 0);
521                 sfree(data);
522                 return 1;
523             }
524
525             /* remove the status line from the input buffer. */
526             bufchain_consume(&p->pending_input_data, eol);
527             if (data[status] != '2') {
528                 /* error */
529                 char buf[1024];
530                 data[eol] = '\0';
531                 while (eol > status &&
532                        (data[eol-1] == '\r' || data[eol-1] == '\n'))
533                     data[--eol] = '\0';
534                 sprintf(buf, "Proxy error: %.900s",
535                         data+status);
536                 plug_closing(p->plug, buf, PROXY_ERROR_GENERAL, 0);
537                 sfree(data);
538                 return 1;
539             }
540
541             sfree(data);
542
543             p->state = 2;
544         }
545
546         if (p->state == 2) {
547
548             /* get headers. we're done when we get a
549              * header of length 2, (ie. just "\r\n")
550              */
551
552             len = bufchain_size(&p->pending_input_data);
553             assert(len > 0);           /* or we wouldn't be here */
554             data = smalloc(len);
555             datap = data;
556             bufchain_fetch(&p->pending_input_data, data, len);
557
558             eol = get_line_end(datap, len);
559             if (eol < 0) {
560                 sfree(data);
561                 return 1;
562             }
563             while (eol > 2)
564             {
565                 bufchain_consume(&p->pending_input_data, eol);
566                 datap += eol;
567                 eol = get_line_end(datap, len);
568             }
569
570             if (eol == 2) {
571                 /* we're done */
572                 bufchain_consume(&p->pending_input_data, 2);
573                 proxy_activate(p);
574                 /* proxy activate will have dealt with
575                  * whatever is left of the buffer */
576                 sfree(data);
577                 return 1;
578             }
579
580             sfree(data);
581             return 1;
582         }
583     }
584
585     plug_closing(p->plug, "Proxy error: unexpected proxy error",
586                  PROXY_ERROR_UNEXPECTED, 0);
587     return 1;
588 }
589
590 /* ----------------------------------------------------------------------
591  * SOCKS proxy type.
592  */
593
594 /* SOCKS version 4 */
595 int proxy_socks4_negotiate (Proxy_Socket p, int change)
596 {
597     if (p->state == PROXY_CHANGE_NEW) {
598
599         /* request format:
600          *  version number (1 byte) = 4
601          *  command code (1 byte)
602          *    1 = CONNECT
603          *    2 = BIND
604          *  dest. port (2 bytes) [network order]
605          *  dest. address (4 bytes)
606          *  user ID (variable length, null terminated string)
607          */
608
609         int length;
610         char * command;
611
612         if (sk_addrtype(p->remote_addr) != AF_INET) {
613             plug_closing(p->plug, "Proxy error: SOCKS version 4 does"
614                          " not support IPv6", PROXY_ERROR_GENERAL, 0);
615             return 1;
616         }
617
618         length = strlen(cfg.proxy_username) + 9;
619         command = (char*) malloc(length);
620         strcpy(command + 8, cfg.proxy_username);
621
622         command[0] = 4; /* version 4 */
623         command[1] = 1; /* CONNECT command */
624
625         /* port */
626         command[2] = (char) (p->remote_port >> 8) & 0xff;
627         command[3] = (char) p->remote_port & 0xff;
628
629         /* address */
630         sk_addrcopy(p->remote_addr, command + 4);
631
632         sk_write(p->sub_socket, command, length);
633         free(command);
634
635         p->state = 1;
636         return 0;
637     }
638
639     if (change == PROXY_CHANGE_CLOSING) {
640         /* if our proxy negotiation process involves closing and opening
641          * new sockets, then we would want to intercept this closing
642          * callback when we were expecting it. if we aren't anticipating
643          * a socket close, then some error must have occurred. we'll
644          * just pass those errors up to the backend.
645          */
646         return plug_closing(p->plug, p->closing_error_msg,
647                             p->closing_error_code,
648                             p->closing_calling_back);
649     }
650
651     if (change == PROXY_CHANGE_SENT) {
652         /* some (or all) of what we wrote to the proxy was sent.
653          * we don't do anything new, however, until we receive the
654          * proxy's response. we might want to set a timer so we can
655          * timeout the proxy negotiation after a while...
656          */
657         return 0;
658     }
659
660     if (change == PROXY_CHANGE_ACCEPTING) {
661         /* we should _never_ see this, as we are using our socket to
662          * connect to a proxy, not accepting inbound connections.
663          * what should we do? close the socket with an appropriate
664          * error message?
665          */
666         return plug_accepting(p->plug, p->accepting_sock);
667     }
668
669     if (change == PROXY_CHANGE_RECEIVE) {
670         /* we have received data from the underlying socket, which
671          * we'll need to parse, process, and respond to appropriately.
672          */
673
674         if (p->state == 1) {
675             /* response format:
676              *  version number (1 byte) = 4
677              *  reply code (1 byte)
678              *    90 = request granted
679              *    91 = request rejected or failed
680              *    92 = request rejected due to lack of IDENTD on client
681              *    93 = request rejected due to difference in user ID 
682              *         (what we sent vs. what IDENTD said)
683              *  dest. port (2 bytes)
684              *  dest. address (4 bytes)
685              */
686
687             char data[8];
688
689             if (bufchain_size(&p->pending_input_data) < 8)
690                 return 1;              /* not got anything yet */
691             
692             /* get the response */
693             bufchain_fetch(&p->pending_input_data, data, 8);
694
695             if (data[0] != 0) {
696                 plug_closing(p->plug, "Proxy error: SOCKS proxy responded with "
697                                       "unexpected reply code version",
698                              PROXY_ERROR_GENERAL, 0);
699                 return 1;
700             }
701
702             if (data[1] != 90) {
703
704                 switch (data[1]) {
705                   case 92:
706                     plug_closing(p->plug, "Proxy error: SOCKS server wanted IDENTD on client",
707                                  PROXY_ERROR_GENERAL, 0);
708                     break;
709                   case 93:
710                     plug_closing(p->plug, "Proxy error: Username and IDENTD on client don't agree",
711                                  PROXY_ERROR_GENERAL, 0);
712                     break;
713                   case 91:
714                   default:
715                     plug_closing(p->plug, "Proxy error: Error while communicating with proxy",
716                                  PROXY_ERROR_GENERAL, 0);
717                     break;
718                 }
719
720                 return 1;
721             }
722             bufchain_consume(&p->pending_input_data, 8);
723
724             /* we're done */
725             proxy_activate(p);
726             /* proxy activate will have dealt with
727              * whatever is left of the buffer */
728             return 1;
729         }
730     }
731
732     plug_closing(p->plug, "Proxy error: unexpected proxy error",
733                  PROXY_ERROR_UNEXPECTED, 0);
734     return 1;
735 }
736
737 /* SOCKS version 5 */
738 int proxy_socks5_negotiate (Proxy_Socket p, int change)
739 {
740     if (p->state == PROXY_CHANGE_NEW) {
741
742         /* initial command:
743          *  version number (1 byte) = 5
744          *  number of available authentication methods (1 byte)
745          *  available authentication methods (1 byte * previous value)
746          *    authentication methods:
747          *     0x00 = no authentication
748          *     0x01 = GSSAPI
749          *     0x02 = username/password
750          *     0x03 = CHAP
751          */
752
753         char command[4];
754         int len;
755
756         command[0] = 5; /* version 5 */
757         if (cfg.proxy_username[0] || cfg.proxy_password[0]) {
758             command[1] = 2;            /* two methods supported: */
759             command[2] = 0x00;         /* no authentication */
760             command[3] = 0x02;         /* username/password */
761             len = 4;
762         } else {
763             command[1] = 1;            /* one methods supported: */
764             command[2] = 0x00;         /* no authentication */
765             len = 3;
766         }
767
768         sk_write(p->sub_socket, command, len);
769
770         p->state = 1;
771         return 0;
772     }
773
774     if (change == PROXY_CHANGE_CLOSING) {
775         /* if our proxy negotiation process involves closing and opening
776          * new sockets, then we would want to intercept this closing
777          * callback when we were expecting it. if we aren't anticipating
778          * a socket close, then some error must have occurred. we'll
779          * just pass those errors up to the backend.
780          */
781         return plug_closing(p->plug, p->closing_error_msg,
782                             p->closing_error_code,
783                             p->closing_calling_back);
784     }
785
786     if (change == PROXY_CHANGE_SENT) {
787         /* some (or all) of what we wrote to the proxy was sent.
788          * we don't do anything new, however, until we receive the
789          * proxy's response. we might want to set a timer so we can
790          * timeout the proxy negotiation after a while...
791          */
792         return 0;
793     }
794
795     if (change == PROXY_CHANGE_ACCEPTING) {
796         /* we should _never_ see this, as we are using our socket to
797          * connect to a proxy, not accepting inbound connections.
798          * what should we do? close the socket with an appropriate
799          * error message?
800          */
801         return plug_accepting(p->plug, p->accepting_sock);
802     }
803
804     if (change == PROXY_CHANGE_RECEIVE) {
805         /* we have received data from the underlying socket, which
806          * we'll need to parse, process, and respond to appropriately.
807          */
808
809         if (p->state == 1) {
810
811             /* initial response:
812              *  version number (1 byte) = 5
813              *  authentication method (1 byte)
814              *    authentication methods:
815              *     0x00 = no authentication
816              *     0x01 = GSSAPI
817              *     0x02 = username/password 
818              *     0x03 = CHAP
819              *     0xff = no acceptable methods
820              */
821             char data[2];
822
823             if (bufchain_size(&p->pending_input_data) < 2)
824                 return 1;              /* not got anything yet */
825
826             /* get the response */
827             bufchain_fetch(&p->pending_input_data, data, 2);
828
829             if (data[0] != 5) {
830                 plug_closing(p->plug, "Proxy error: SOCKS proxy returned unexpected version",
831                              PROXY_ERROR_GENERAL, 0);
832                 return 1;
833             }
834
835             if (data[1] == 0x00) p->state = 2; /* no authentication needed */
836             else if (data[1] == 0x01) p->state = 4; /* GSSAPI authentication */
837             else if (data[1] == 0x02) p->state = 5; /* username/password authentication */
838             else if (data[1] == 0x03) p->state = 6; /* CHAP authentication */
839             else {
840                 plug_closing(p->plug, "Proxy error: SOCKS proxy did not accept our authentication",
841                              PROXY_ERROR_GENERAL, 0);
842                 return 1;
843             }
844             bufchain_consume(&p->pending_input_data, 2);
845         }
846
847         if (p->state == 7) {
848
849             /* password authentication reply format:
850              *  version number (1 bytes) = 1
851              *  reply code (1 byte)
852              *    0 = succeeded
853              *    >0 = failed
854              */
855             char data[2];
856
857             if (bufchain_size(&p->pending_input_data) < 2)
858                 return 1;              /* not got anything yet */
859
860             /* get the response */
861             bufchain_fetch(&p->pending_input_data, data, 2);
862
863             if (data[0] != 1) {
864                 plug_closing(p->plug, "Proxy error: SOCKS password "
865                              "subnegotiation contained wrong version number",
866                              PROXY_ERROR_GENERAL, 0);
867                 return 1;
868             }
869
870             if (data[1] != 0) {
871
872                 plug_closing(p->plug, "Proxy error: SOCKS proxy refused"
873                              " password authentication",
874                              PROXY_ERROR_GENERAL, 0);
875                 return 1;
876             }
877
878             bufchain_consume(&p->pending_input_data, 2);
879             p->state = 2;              /* now proceed as authenticated */
880         }
881
882         if (p->state == 2) {
883
884             /* request format:
885              *  version number (1 byte) = 5
886              *  command code (1 byte)
887              *    1 = CONNECT
888              *    2 = BIND
889              *    3 = UDP ASSOCIATE
890              *  reserved (1 byte) = 0x00
891              *  address type (1 byte)
892              *    1 = IPv4
893              *    3 = domainname (first byte has length, no terminating null)
894              *    4 = IPv6
895              *  dest. address (variable)
896              *  dest. port (2 bytes) [network order]
897              */
898
899             char command[22];
900             int len;
901
902             if (sk_addrtype(p->remote_addr) == AF_INET) {
903                 len = 10;
904                 command[3] = 1; /* IPv4 */
905             } else {
906                 len = 22;
907                 command[3] = 4; /* IPv6 */
908             }
909
910             command[0] = 5; /* version 5 */
911             command[1] = 1; /* CONNECT command */
912             command[2] = 0x00;
913
914             /* address */
915             sk_addrcopy(p->remote_addr, command+4);
916
917             /* port */
918             command[len-2] = (char) (p->remote_port >> 8) & 0xff;
919             command[len-1] = (char) p->remote_port & 0xff;
920
921             sk_write(p->sub_socket, command, len);
922
923             p->state = 3;
924             return 1;
925         }
926
927         if (p->state == 3) {
928
929             /* reply format:
930              *  version number (1 bytes) = 5
931              *  reply code (1 byte)
932              *    0 = succeeded
933              *    1 = general SOCKS server failure
934              *    2 = connection not allowed by ruleset
935              *    3 = network unreachable
936              *    4 = host unreachable
937              *    5 = connection refused
938              *    6 = TTL expired
939              *    7 = command not supported
940              *    8 = address type not supported
941              * reserved (1 byte) = x00
942              * address type (1 byte)
943              *    1 = IPv4
944              *    3 = domainname (first byte has length, no terminating null)
945              *    4 = IPv6
946              * server bound address (variable)
947              * server bound port (2 bytes) [network order]
948              */
949             char data[5];
950             int len;
951
952             /* First 5 bytes of packet are enough to tell its length. */ 
953             if (bufchain_size(&p->pending_input_data) < 5)
954                 return 1;              /* not got anything yet */
955
956             /* get the response */
957             bufchain_fetch(&p->pending_input_data, data, 5);
958
959             if (data[0] != 5) {
960                 plug_closing(p->plug, "Proxy error: SOCKS proxy returned wrong version number",
961                              PROXY_ERROR_GENERAL, 0);
962                 return 1;
963             }
964
965             if (data[1] != 0) {
966                 char buf[256];
967
968                 strcpy(buf, "Proxy error: ");
969
970                 switch (data[1]) {
971                   case 1: strcat(buf, "General SOCKS server failure"); break;
972                   case 2: strcat(buf, "Connection not allowed by ruleset"); break;
973                   case 3: strcat(buf, "Network unreachable"); break;
974                   case 4: strcat(buf, "Host unreachable"); break;
975                   case 5: strcat(buf, "Connection refused"); break;
976                   case 6: strcat(buf, "TTL expired"); break;
977                   case 7: strcat(buf, "Command not supported"); break;
978                   case 8: strcat(buf, "Address type not supported"); break;
979                   default: sprintf(buf+strlen(buf),
980                                    "Unrecognised SOCKS error code %d",
981                                    data[1]);
982                     break;
983                 }
984                 plug_closing(p->plug, buf, PROXY_ERROR_GENERAL, 0);
985
986                 return 1;
987             }
988
989             /*
990              * Eat the rest of the reply packet.
991              */
992             len = 6;                   /* first 4 bytes, last 2 */
993             switch (data[3]) {
994               case 1: len += 4; break; /* IPv4 address */
995               case 4: len += 16; break;/* IPv6 address */
996               case 3: len += (unsigned char)data[4]; break; /* domain name */
997               default:
998                 plug_closing(p->plug, "Proxy error: SOCKS proxy returned "
999                              "unrecognised address format",
1000                              PROXY_ERROR_GENERAL, 0);
1001                 return 1;
1002             }
1003             if (bufchain_size(&p->pending_input_data) < len)
1004                 return 1;              /* not got whole reply yet */
1005             bufchain_consume(&p->pending_input_data, len);
1006
1007             /* we're done */
1008             proxy_activate(p);
1009             return 1;
1010         }
1011
1012         if (p->state == 4) {
1013             /* TODO: Handle GSSAPI authentication */
1014             plug_closing(p->plug, "Proxy error: We don't support GSSAPI authentication",
1015                          PROXY_ERROR_GENERAL, 0);
1016             return 1;
1017         }
1018
1019         if (p->state == 5) {
1020             if (cfg.proxy_username[0] || cfg.proxy_password[0]) {
1021                 char userpwbuf[514];
1022                 int ulen, plen;
1023                 ulen = strlen(cfg.proxy_username);
1024                 if (ulen > 255) ulen = 255; if (ulen < 1) ulen = 1;
1025                 plen = strlen(cfg.proxy_password);
1026                 if (plen > 255) plen = 255; if (plen < 1) plen = 1;
1027                 userpwbuf[0] = 1;      /* version number of subnegotiation */
1028                 userpwbuf[1] = ulen;
1029                 memcpy(userpwbuf+2, cfg.proxy_username, ulen);
1030                 userpwbuf[ulen+2] = plen;
1031                 memcpy(userpwbuf+ulen+3, cfg.proxy_password, plen);
1032                 sk_write(p->sub_socket, userpwbuf, ulen + plen + 3);
1033                 p->state = 7;
1034             } else 
1035                 plug_closing(p->plug, "Proxy error: Server chose "
1036                              "username/password authentication but we "
1037                              "didn't offer it!",
1038                          PROXY_ERROR_GENERAL, 0);
1039             return 1;
1040         }
1041
1042         if (p->state == 6) {
1043             /* TODO: Handle CHAP authentication */
1044             plug_closing(p->plug, "Proxy error: We don't support CHAP authentication",
1045                          PROXY_ERROR_GENERAL, 0);
1046             return 1;
1047         }
1048
1049     }
1050
1051     plug_closing(p->plug, "Proxy error: Unexpected proxy error",
1052                  PROXY_ERROR_UNEXPECTED, 0);
1053     return 1;
1054 }
1055
1056 /* ----------------------------------------------------------------------
1057  * `Telnet' proxy type.
1058  *
1059  * (This is for ad-hoc proxies where you connect to the proxy's
1060  * telnet port and send a command such as `connect host port'. The
1061  * command is configurable, since this proxy type is typically not
1062  * standardised or at all well-defined.)
1063  */
1064
1065 int proxy_telnet_negotiate (Proxy_Socket p, int change)
1066 {
1067     if (p->state == PROXY_CHANGE_NEW) {
1068
1069         int so = 0, eo = 0;
1070
1071         /* we need to escape \\, \%, \r, \n, \t, \x??, \0???, 
1072          * %%, %host, and %port 
1073          */
1074
1075         while (cfg.proxy_telnet_command[eo] != 0) {
1076
1077             /* scan forward until we hit end-of-line, 
1078              * or an escape character (\ or %) */
1079             while (cfg.proxy_telnet_command[eo] != 0 &&
1080                    cfg.proxy_telnet_command[eo] != '%' &&
1081                    cfg.proxy_telnet_command[eo] != '\\') eo++;
1082
1083             /* if we hit eol, break out of our escaping loop */
1084             if (cfg.proxy_telnet_command[eo] == 0) break;
1085
1086             /* if there was any unescaped text before the escape
1087              * character, send that now */
1088             if (eo != so) {
1089                 sk_write(p->sub_socket, 
1090                          cfg.proxy_telnet_command + so, eo - so);
1091             }
1092
1093             so = eo++;
1094
1095             /* if the escape character was the last character of
1096              * the line, we'll just stop and send it. */
1097             if (cfg.proxy_telnet_command[eo] == 0) break;
1098
1099             if (cfg.proxy_telnet_command[so] == '\\') {
1100
1101                 /* we recognize \\, \%, \r, \n, \t, \x??. 
1102                  * anything else, we just send unescaped (including the \). 
1103                  */
1104
1105                 switch (cfg.proxy_telnet_command[eo]) {
1106
1107                   case '\\':
1108                     sk_write(p->sub_socket, "\\", 1);
1109                     eo++;
1110                     break;
1111
1112                   case '%':
1113                     sk_write(p->sub_socket, "%%", 1);
1114                     eo++;
1115                     break;
1116
1117                   case 'r':
1118                     sk_write(p->sub_socket, "\r", 1);
1119                     eo++;
1120                     break;
1121
1122                   case 'n':
1123                     sk_write(p->sub_socket, "\n", 1);
1124                     eo++;
1125                     break;
1126
1127                   case 't':
1128                     sk_write(p->sub_socket, "\t", 1);
1129                     eo++;
1130                     break;
1131
1132                   case 'x':
1133                   case 'X':
1134                     {
1135                     /* escaped hexadecimal value (ie. \xff) */
1136                     unsigned char v = 0;
1137                     int i = 0;
1138
1139                     for (;;) {
1140                         eo++;
1141                         if (cfg.proxy_telnet_command[eo] >= '0' &&
1142                             cfg.proxy_telnet_command[eo] <= '9')
1143                             v += cfg.proxy_telnet_command[eo] - '0';
1144                         else if (cfg.proxy_telnet_command[eo] >= 'a' &&
1145                                  cfg.proxy_telnet_command[eo] <= 'f')
1146                             v += cfg.proxy_telnet_command[eo] - 'a' + 10;
1147                         else if (cfg.proxy_telnet_command[eo] >= 'A' &&
1148                                  cfg.proxy_telnet_command[eo] <= 'F')
1149                             v += cfg.proxy_telnet_command[eo] - 'A' + 10;
1150                         else {
1151                             /* non hex character, so we abort and just
1152                              * send the whole thing unescaped (including \x)
1153                              */
1154                             sk_write(p->sub_socket, "\\", 1);
1155                             eo = so + 1;
1156                             break;
1157                         }
1158
1159                         /* we only extract two hex characters */
1160                         if (i == 1) {
1161                             sk_write(p->sub_socket, &v, 1);
1162                             eo++;
1163                             break;
1164                         }
1165
1166                         i++;
1167                         v <<= 4;
1168                     }
1169                     }
1170                     break;
1171
1172                   default:
1173                     sk_write(p->sub_socket, 
1174                              cfg.proxy_telnet_command + so, 2);
1175                     eo++;
1176                     break;
1177                 }
1178             } else {
1179
1180                 /* % escape. we recognize %%, %host, %port. anything else,
1181                  * we just send unescaped (including the %). */
1182
1183                 if (cfg.proxy_telnet_command[eo] == '%') {
1184                     sk_write(p->sub_socket, "%", 1);
1185                     eo++;
1186                 } 
1187                 else if (strnicmp(cfg.proxy_telnet_command + eo,
1188                                   "host", 4) == 0) {
1189                     char dest[64];
1190                     sk_getaddr(p->remote_addr, dest, 64);
1191                     sk_write(p->sub_socket, dest, strlen(dest));
1192                     eo += 4;
1193                 } 
1194                 else if (strnicmp(cfg.proxy_telnet_command + eo,
1195                                   "port", 4) == 0) {
1196                     char port[8];
1197                     sprintf(port, "%i", p->remote_port);
1198                     sk_write(p->sub_socket, port, strlen(port));
1199                     eo += 4;
1200                 } 
1201                 else {
1202                     /* we don't escape this, so send the % now, and
1203                      * don't advance eo, so that we'll consider the
1204                      * text immediately following the % as unescaped.
1205                      */
1206                     sk_write(p->sub_socket, "%", 1);
1207                 }
1208             }
1209
1210             /* resume scanning for additional escapes after this one. */
1211             so = eo;
1212         }
1213
1214         /* if there is any unescaped text at the end of the line, send it */
1215         if (eo != so) {
1216             sk_write(p->sub_socket, cfg.proxy_telnet_command + so, eo - so);
1217         }
1218
1219         p->state = 1;
1220         return 0;
1221     }
1222
1223     if (change == PROXY_CHANGE_CLOSING) {
1224         /* if our proxy negotiation process involves closing and opening
1225          * new sockets, then we would want to intercept this closing
1226          * callback when we were expecting it. if we aren't anticipating
1227          * a socket close, then some error must have occurred. we'll
1228          * just pass those errors up to the backend.
1229          */
1230         return plug_closing(p->plug, p->closing_error_msg,
1231                             p->closing_error_code,
1232                             p->closing_calling_back);
1233     }
1234
1235     if (change == PROXY_CHANGE_SENT) {
1236         /* some (or all) of what we wrote to the proxy was sent.
1237          * we don't do anything new, however, until we receive the
1238          * proxy's response. we might want to set a timer so we can
1239          * timeout the proxy negotiation after a while...
1240          */
1241         return 0;
1242     }
1243
1244     if (change == PROXY_CHANGE_ACCEPTING) {
1245         /* we should _never_ see this, as we are using our socket to
1246          * connect to a proxy, not accepting inbound connections.
1247          * what should we do? close the socket with an appropriate
1248          * error message?
1249          */
1250         return plug_accepting(p->plug, p->accepting_sock);
1251     }
1252
1253     if (change == PROXY_CHANGE_RECEIVE) {
1254         /* we have received data from the underlying socket, which
1255          * we'll need to parse, process, and respond to appropriately.
1256          */
1257
1258         /* we're done */
1259         proxy_activate(p);
1260         /* proxy activate will have dealt with
1261          * whatever is left of the buffer */
1262         return 1;
1263     }
1264
1265     plug_closing(p->plug, "Proxy error: Unexpected proxy error",
1266                  PROXY_ERROR_UNEXPECTED, 0);
1267     return 1;
1268 }