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