]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - portfwd.c
Chas Honton's patch to dynamic port forwarding: should allow longer
[PuTTY.git] / portfwd.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include "putty.h"
5 #include "ssh.h"
6
7 #ifndef FALSE
8 #define FALSE 0
9 #endif
10 #ifndef TRUE
11 #define TRUE 1
12 #endif
13
14 #define GET_32BIT_LSB_FIRST(cp) \
15   (((unsigned long)(unsigned char)(cp)[0]) | \
16   ((unsigned long)(unsigned char)(cp)[1] << 8) | \
17   ((unsigned long)(unsigned char)(cp)[2] << 16) | \
18   ((unsigned long)(unsigned char)(cp)[3] << 24))
19
20 #define PUT_32BIT_LSB_FIRST(cp, value) ( \
21   (cp)[0] = (value), \
22   (cp)[1] = (value) >> 8, \
23   (cp)[2] = (value) >> 16, \
24   (cp)[3] = (value) >> 24 )
25
26 #define GET_16BIT_LSB_FIRST(cp) \
27   (((unsigned long)(unsigned char)(cp)[0]) | \
28   ((unsigned long)(unsigned char)(cp)[1] << 8))
29
30 #define PUT_16BIT_LSB_FIRST(cp, value) ( \
31   (cp)[0] = (value), \
32   (cp)[1] = (value) >> 8 )
33
34 #define GET_32BIT_MSB_FIRST(cp) \
35   (((unsigned long)(unsigned char)(cp)[0] << 24) | \
36   ((unsigned long)(unsigned char)(cp)[1] << 16) | \
37   ((unsigned long)(unsigned char)(cp)[2] << 8) | \
38   ((unsigned long)(unsigned char)(cp)[3]))
39
40 #define PUT_32BIT_MSB_FIRST(cp, value) ( \
41   (cp)[0] = (value) >> 24, \
42   (cp)[1] = (value) >> 16, \
43   (cp)[2] = (value) >> 8, \
44   (cp)[3] = (value) )
45
46 #define GET_16BIT_MSB_FIRST(cp) \
47   (((unsigned long)(unsigned char)(cp)[0] << 8) | \
48   ((unsigned long)(unsigned char)(cp)[1]))
49
50 #define PUT_16BIT_MSB_FIRST(cp, value) ( \
51   (cp)[0] = (value) >> 8, \
52   (cp)[1] = (value) )
53
54 struct PFwdPrivate {
55     const struct plug_function_table *fn;
56     /* the above variable absolutely *must* be the first in this structure */
57     void *c;                           /* (channel) data used by ssh.c */
58     void *backhandle;                  /* instance of SSH backend itself */
59     /* Note that backhandle need not be filled in if c is non-NULL */
60     Socket s;
61     int throttled, throttle_override;
62     int ready;
63     /*
64      * `dynamic' does double duty. It's set to 0 for an ordinary
65      * forwarded port, and nonzero for SOCKS-style dynamic port
66      * forwarding; but it also represents the state of the SOCKS
67      * exchange.
68      */
69     int dynamic;
70     /*
71      * `hostname' and `port' are the real hostname and port, once
72      * we know what we're connecting to; they're unused for this
73      * purpose while conducting a local SOCKS exchange, which means
74      * we can also use them as a buffer and pointer for reading
75      * data from the SOCKS client.
76      */
77     char hostname[256+8];
78     int port;
79     /*
80      * When doing dynamic port forwarding, we can receive
81      * connection data before we are actually able to send it; so
82      * we may have to temporarily hold some in a dynamically
83      * allocated buffer here.
84      */
85     void *buffer;
86     int buflen;
87 };
88
89 static int pfd_closing(Plug plug, char *error_msg, int error_code,
90                        int calling_back)
91 {
92     struct PFwdPrivate *pr = (struct PFwdPrivate *) plug;
93
94     /*
95      * We have no way to communicate down the forwarded connection,
96      * so if an error occurred on the socket, we just ignore it
97      * and treat it like a proper close.
98      */
99     if (pr->c)
100         sshfwd_close(pr->c);
101     pfd_close(pr->s);
102     return 1;
103 }
104
105 static int pfd_receive(Plug plug, int urgent, char *data, int len)
106 {
107     struct PFwdPrivate *pr = (struct PFwdPrivate *) plug;
108     if (pr->dynamic) {
109         while (len--) {
110             if (pr->port >= lenof(pr->hostname)) {
111                 if ((pr->dynamic >> 12) == 4) {
112                     /* Send back a SOCKS 4 error before closing. */
113                     char data[8];
114                     memset(data, 0, sizeof(data));
115                     data[1] = 91;      /* generic `request rejected' */
116                     sk_write(pr->s, data, 8);
117                 }
118                 pfd_close(pr->s);
119                 return 1;
120             }
121             pr->hostname[pr->port++] = *data++;
122
123             /*
124              * Now check what's in the buffer to see if it's a
125              * valid and complete message in the SOCKS exchange.
126              */
127             if ((pr->dynamic == 1 || (pr->dynamic >> 12) == 4) &&
128                 pr->hostname[0] == 4) {
129                 /*
130                  * SOCKS 4.
131                  */
132                 if (pr->dynamic == 1)
133                     pr->dynamic = 0x4000;
134                 if (pr->port < 2) continue;/* don't have command code yet */
135                 if (pr->hostname[1] != 1) {
136                     /* Send back a SOCKS 4 error before closing. */
137                     char data[8];
138                     memset(data, 0, sizeof(data));
139                     data[1] = 91;      /* generic `request rejected' */
140                     sk_write(pr->s, data, 8);
141                     pfd_close(pr->s);
142                     return 1;
143                 }
144                 if (pr->port < 8) continue;   /* haven't started username */
145                 if (pr->hostname[pr->port-1] != 0)
146                     continue;          /* haven't _finished_ username */
147                 /*
148                  * Now we have a full SOCKS 4 request. Check it to
149                  * see if it's a SOCKS 4A request.
150                  */
151                 if (pr->hostname[4] == 0 && pr->hostname[5] == 0 &&
152                     pr->hostname[6] == 0 && pr->hostname[7] != 0) {
153                     /*
154                      * It's SOCKS 4A. So if we haven't yet
155                      * collected the host name, we should continue
156                      * waiting for data in order to do so; if we
157                      * have, we can go ahead.
158                      */
159                     int len;
160                     if (pr->dynamic == 0x4000) {
161                         pr->dynamic = 0x4001;
162                         pr->port = 8;      /* reset buffer to overwrite name */
163                         continue;
164                     }
165                     pr->hostname[0] = 0;   /* reply version code */
166                     pr->hostname[1] = 90;   /* request granted */
167                     sk_write(pr->s, pr->hostname, 8);
168                     len= pr->port;
169                     pr->port = GET_16BIT_MSB_FIRST(pr->hostname+2);
170                     memmove(pr->hostname, pr->hostname + 8, len);
171                     goto connect;
172                 } else {
173                     /*
174                      * It's SOCKS 4, which means we should format
175                      * the IP address into the hostname string and
176                      * then just go.
177                      */
178                     pr->hostname[0] = 0;   /* reply version code */
179                     pr->hostname[1] = 90;   /* request granted */
180                     sk_write(pr->s, pr->hostname, 8);
181                     pr->port = GET_16BIT_MSB_FIRST(pr->hostname+2);
182                     sprintf(pr->hostname, "%d.%d.%d.%d",
183                             (unsigned char)pr->hostname[4],
184                             (unsigned char)pr->hostname[5],
185                             (unsigned char)pr->hostname[6],
186                             (unsigned char)pr->hostname[7]);
187                     goto connect;
188                 }
189             }
190
191             if ((pr->dynamic == 1 || (pr->dynamic >> 12) == 5) &&
192                 pr->hostname[0] == 5) {
193                 /*
194                  * SOCKS 5.
195                  */
196                 if (pr->dynamic == 1)
197                     pr->dynamic = 0x5000;
198
199                 if (pr->dynamic == 0x5000) {
200                     int i, method;
201                     char data[2];
202                     /*
203                      * We're receiving a set of method identifiers.
204                      */
205                     if (pr->port < 2) continue;/* no method count yet */
206                     if (pr->port < 2 + (unsigned char)pr->hostname[1])
207                         continue;      /* no methods yet */
208                     method = 0xFF;     /* invalid */
209                     for (i = 0; i < (unsigned char)pr->hostname[1]; i++)
210                         if (pr->hostname[2+i] == 0) {
211                             method = 0;/* no auth */
212                             break;
213                         }
214                     data[0] = 5;
215                     data[1] = method;
216                     sk_write(pr->s, data, 2);
217                     pr->dynamic = 0x5001;
218                     pr->port = 0;      /* re-empty the buffer */
219                     continue;
220                 }
221
222                 if (pr->dynamic == 0x5001) {
223                     int atype, alen;
224                     if (pr->port < 6) continue;
225                     atype = (unsigned char)pr->hostname[3];
226                     if (atype == 1)    /* IPv4 address */
227                         alen = 4;
228                     if (atype == 4)    /* IPv6 address */
229                         alen = 16;
230                     if (atype == 3)    /* domain name has leading length */
231                         alen = 1 + (unsigned char)pr->hostname[4];
232                     if (pr->port < 6 + alen) continue;
233                     if (pr->hostname[1] != 1 || pr->hostname[2] != 0) {
234                         pr->hostname[1] = 1;   /* generic failure */
235                         pr->hostname[2] = 0;   /* reserved */
236                         sk_write(pr->s, pr->hostname, pr->port);
237                         pfd_close(pr->s);
238                         return 1;
239                     }
240                     /*
241                      * Now we have a viable connect request. Switch
242                      * on atype.
243                      */
244                     pr->port = GET_16BIT_MSB_FIRST(pr->hostname+4+alen);
245                     if (atype == 1) {
246                         pr->hostname[1] = 0;   /* succeeded */
247                         sk_write(pr->s, pr->hostname, alen + 6);
248                         sprintf(pr->hostname, "%d.%d.%d.%d",
249                                 (unsigned char)pr->hostname[4],
250                                 (unsigned char)pr->hostname[5],
251                                 (unsigned char)pr->hostname[6],
252                                 (unsigned char)pr->hostname[7]);
253                         goto connect;
254                     } else if (atype == 3) {
255                         pr->hostname[1] = 0;   /* succeeded */
256                         sk_write(pr->s, pr->hostname, alen + 6);
257                         memmove(pr->hostname, pr->hostname + 5, alen-1);
258                         pr->hostname[alen-1] = '\0';
259                         goto connect;
260                     } else {
261                         /*
262                          * Unknown address type. (FIXME: support IPv6!)
263                          */
264                         pr->hostname[1] = 8;   /* atype not supported */
265                         sk_write(pr->s, pr->hostname, pr->port);
266                         pfd_close(pr->s);
267                         return 1;                       
268                     }
269                 }
270             }
271             
272             /*
273              * If we get here without either having done `continue'
274              * or `goto connect', it must be because there is no
275              * sensible interpretation of what's in our buffer. So
276              * close the connection rudely.
277              */
278             pfd_close(pr->s);
279             return 1;
280         }
281         return 1;
282
283         /*
284          * We come here when we're ready to make an actual
285          * connection.
286          */
287         connect:
288
289         pr->c = new_sock_channel(pr->backhandle, pr->s);
290         if (pr->c == NULL) {
291             pfd_close(pr->s);
292             return 1;
293         } else {
294             /* asks to forward to the specified host/port for this */
295             ssh_send_port_open(pr->c, pr->hostname, pr->port, "forwarding");
296         }
297         pr->dynamic = 0;
298
299         /*
300          * Now freeze the socket until the SSH server confirms the
301          * connection.
302          */
303         sk_set_frozen(pr->s, 1);
304         /*
305          * If there's any data remaining in our current buffer,
306          * save it to be sent on pfd_confirm().
307          */
308         if (len > 0) {
309             pr->buffer = snewn(len, char);
310             memcpy(pr->buffer, data, len);
311             pr->buflen = len;
312         }
313     }
314     if (pr->ready) {
315         if (sshfwd_write(pr->c, data, len) > 0) {
316             pr->throttled = 1;
317             sk_set_frozen(pr->s, 1);
318         }
319     }
320     return 1;
321 }
322
323 static void pfd_sent(Plug plug, int bufsize)
324 {
325     struct PFwdPrivate *pr = (struct PFwdPrivate *) plug;
326
327     if (pr->c)
328         sshfwd_unthrottle(pr->c, bufsize);
329 }
330
331 /*
332  * Called when receiving a PORT OPEN from the server
333  */
334 char *pfd_newconnect(Socket *s, char *hostname, int port, void *c,
335                      const Config *cfg)
336 {
337     static const struct plug_function_table fn_table = {
338         pfd_closing,
339         pfd_receive,
340         pfd_sent,
341         NULL
342     };
343
344     SockAddr addr;
345     char *err, *dummy_realhost;
346     struct PFwdPrivate *pr;
347
348     /*
349      * Try to find host.
350      */
351     addr = name_lookup(hostname, port, &dummy_realhost, cfg);
352     if ((err = sk_addr_error(addr)) != NULL)
353         return err;
354
355     /*
356      * Open socket.
357      */
358     pr = snew(struct PFwdPrivate);
359     pr->buffer = NULL;
360     pr->fn = &fn_table;
361     pr->throttled = pr->throttle_override = 0;
362     pr->ready = 1;
363     pr->c = c;
364     pr->backhandle = NULL;             /* we shouldn't need this */
365
366     pr->s = *s = new_connection(addr, dummy_realhost, port,
367                                 0, 1, 0, (Plug) pr, cfg);
368     if ((err = sk_socket_error(*s)) != NULL) {
369         sfree(pr);
370         return err;
371     }
372
373     sk_set_private_ptr(*s, pr);
374     sk_addr_free(addr);
375     return NULL;
376 }
377
378 /*
379  called when someone connects to the local port
380  */
381
382 static int pfd_accepting(Plug p, void *sock)
383 {
384     static const struct plug_function_table fn_table = {
385         pfd_closing,
386         pfd_receive,
387         pfd_sent,
388         NULL
389     };
390     struct PFwdPrivate *pr, *org;
391     Socket s;
392     char *err;
393
394     org = (struct PFwdPrivate *)p;
395     pr = snew(struct PFwdPrivate);
396     pr->buffer = NULL;
397     pr->fn = &fn_table;
398
399     pr->c = NULL;
400     pr->backhandle = org->backhandle;
401
402     pr->s = s = sk_register(sock, (Plug) pr);
403     if ((err = sk_socket_error(s)) != NULL) {
404         sfree(pr);
405         return err != NULL;
406     }
407
408     sk_set_private_ptr(s, pr);
409
410     pr->throttled = pr->throttle_override = 0;
411     pr->ready = 0;
412
413     if (org->dynamic) {
414         pr->dynamic = 1;
415         pr->port = 0;                  /* hostname buffer is so far empty */
416         sk_set_frozen(s, 0);           /* we want to receive SOCKS _now_! */
417     } else {
418         strcpy(pr->hostname, org->hostname);
419         pr->port = org->port;   
420         pr->c = new_sock_channel(org->backhandle, s);
421
422         if (pr->c == NULL) {
423             sfree(pr);
424             return 1;
425         } else {
426             /* asks to forward to the specified host/port for this */
427             ssh_send_port_open(pr->c, pr->hostname, pr->port, "forwarding");
428         }
429     }
430
431     return 0;
432 }
433
434
435 /* Add a new forwarding from port -> desthost:destport
436  sets up a listener on the local machine on (srcaddr:)port
437  */
438 char *pfd_addforward(char *desthost, int destport, char *srcaddr, int port,
439                      void *backhandle, const Config *cfg)
440 {
441     static const struct plug_function_table fn_table = {
442         pfd_closing,
443         pfd_receive,                   /* should not happen... */
444         pfd_sent,                      /* also should not happen */
445         pfd_accepting
446     };
447
448     char *err;
449     struct PFwdPrivate *pr;
450     Socket s;
451
452     /*
453      * Open socket.
454      */
455     pr = snew(struct PFwdPrivate);
456     pr->buffer = NULL;
457     pr->fn = &fn_table;
458     pr->c = NULL;
459     if (desthost) {
460         strcpy(pr->hostname, desthost);
461         pr->port = destport;
462         pr->dynamic = 0;
463     } else
464         pr->dynamic = 1;
465     pr->throttled = pr->throttle_override = 0;
466     pr->ready = 0;
467     pr->backhandle = backhandle;
468
469     pr->s = s = new_listener(srcaddr, port, (Plug) pr,
470                              !cfg->lport_acceptall, cfg);
471     if ((err = sk_socket_error(s)) != NULL) {
472         sfree(pr);
473         return err;
474     }
475
476     sk_set_private_ptr(s, pr);
477
478     return NULL;
479 }
480
481 void pfd_close(Socket s)
482 {
483     struct PFwdPrivate *pr;
484
485     if (!s)
486         return;
487
488     pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
489
490     sfree(pr->buffer);
491     sfree(pr);
492
493     sk_close(s);
494 }
495
496 void pfd_unthrottle(Socket s)
497 {
498     struct PFwdPrivate *pr;
499     if (!s)
500         return;
501     pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
502
503     pr->throttled = 0;
504     sk_set_frozen(s, pr->throttled || pr->throttle_override);
505 }
506
507 void pfd_override_throttle(Socket s, int enable)
508 {
509     struct PFwdPrivate *pr;
510     if (!s)
511         return;
512     pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
513
514     pr->throttle_override = enable;
515     sk_set_frozen(s, pr->throttled || pr->throttle_override);
516 }
517
518 /*
519  * Called to send data down the raw connection.
520  */
521 int pfd_send(Socket s, char *data, int len)
522 {
523     if (s == NULL)
524         return 0;
525     return sk_write(s, data, len);
526 }
527
528
529 void pfd_confirm(Socket s)
530 {
531     struct PFwdPrivate *pr;
532
533     if (s == NULL)
534         return;
535
536     pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
537     pr->ready = 1;
538     sk_set_frozen(s, 0);
539     sk_write(s, NULL, 0);
540     if (pr->buffer) {
541         sshfwd_write(pr->c, pr->buffer, pr->buflen);
542         sfree(pr->buffer);
543         pr->buffer = NULL;
544     }
545 }