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