]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - portfwd.c
In SOCKS5 dynamic forwarding, we were echoing back DST.{ADDR,PORT} as
[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, const 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                 /* Request too long. */
112                 if ((pr->dynamic >> 12) == 4) {
113                     /* Send back a SOCKS 4 error before closing. */
114                     char data[8];
115                     memset(data, 0, sizeof(data));
116                     data[1] = 91;      /* generic `request rejected' */
117                     sk_write(pr->s, data, 8);
118                 }
119                 pfd_close(pr->s);
120                 return 1;
121             }
122             pr->hostname[pr->port++] = *data++;
123
124             /*
125              * Now check what's in the buffer to see if it's a
126              * valid and complete message in the SOCKS exchange.
127              */
128             if ((pr->dynamic == 1 || (pr->dynamic >> 12) == 4) &&
129                 pr->hostname[0] == 4) {
130                 /*
131                  * SOCKS 4.
132                  */
133                 if (pr->dynamic == 1)
134                     pr->dynamic = 0x4000;
135                 if (pr->port < 2) continue;/* don't have command code yet */
136                 if (pr->hostname[1] != 1) {
137                     /* Send back a SOCKS 4 error before closing. */
138                     char data[8];
139                     memset(data, 0, sizeof(data));
140                     data[1] = 91;      /* generic `request rejected' */
141                     sk_write(pr->s, data, 8);
142                     pfd_close(pr->s);
143                     return 1;
144                 }
145                 if (pr->port < 8) continue;   /* haven't started username */
146                 if (pr->hostname[pr->port-1] != 0)
147                     continue;          /* haven't _finished_ username */
148                 /*
149                  * Now we have a full SOCKS 4 request. Check it to
150                  * see if it's a SOCKS 4A request.
151                  */
152                 if (pr->hostname[4] == 0 && pr->hostname[5] == 0 &&
153                     pr->hostname[6] == 0 && pr->hostname[7] != 0) {
154                     /*
155                      * It's SOCKS 4A. So if we haven't yet
156                      * collected the host name, we should continue
157                      * waiting for data in order to do so; if we
158                      * have, we can go ahead.
159                      */
160                     int len;
161                     if (pr->dynamic == 0x4000) {
162                         pr->dynamic = 0x4001;
163                         pr->port = 8;      /* reset buffer to overwrite name */
164                         continue;
165                     }
166                     pr->hostname[0] = 0;   /* reply version code */
167                     pr->hostname[1] = 90;   /* request granted */
168                     sk_write(pr->s, pr->hostname, 8);
169                     len= pr->port;
170                     pr->port = GET_16BIT_MSB_FIRST(pr->hostname+2);
171                     memmove(pr->hostname, pr->hostname + 8, len);
172                     goto connect;
173                 } else {
174                     /*
175                      * It's SOCKS 4, which means we should format
176                      * the IP address into the hostname string and
177                      * then just go.
178                      */
179                     pr->hostname[0] = 0;   /* reply version code */
180                     pr->hostname[1] = 90;   /* request granted */
181                     sk_write(pr->s, pr->hostname, 8);
182                     pr->port = GET_16BIT_MSB_FIRST(pr->hostname+2);
183                     sprintf(pr->hostname, "%d.%d.%d.%d",
184                             (unsigned char)pr->hostname[4],
185                             (unsigned char)pr->hostname[5],
186                             (unsigned char)pr->hostname[6],
187                             (unsigned char)pr->hostname[7]);
188                     goto connect;
189                 }
190             }
191
192             if ((pr->dynamic == 1 || (pr->dynamic >> 12) == 5) &&
193                 pr->hostname[0] == 5) {
194                 /*
195                  * SOCKS 5.
196                  */
197                 if (pr->dynamic == 1)
198                     pr->dynamic = 0x5000;
199
200                 if (pr->dynamic == 0x5000) {
201                     int i, method;
202                     char data[2];
203                     /*
204                      * We're receiving a set of method identifiers.
205                      */
206                     if (pr->port < 2) continue;/* no method count yet */
207                     if (pr->port < 2 + (unsigned char)pr->hostname[1])
208                         continue;      /* no methods yet */
209                     method = 0xFF;     /* invalid */
210                     for (i = 0; i < (unsigned char)pr->hostname[1]; i++)
211                         if (pr->hostname[2+i] == 0) {
212                             method = 0;/* no auth */
213                             break;
214                         }
215                     data[0] = 5;
216                     data[1] = method;
217                     sk_write(pr->s, data, 2);
218                     pr->dynamic = 0x5001;
219                     pr->port = 0;      /* re-empty the buffer */
220                     continue;
221                 }
222
223                 if (pr->dynamic == 0x5001) {
224                     /*
225                      * We're receiving a SOCKS request.
226                      */
227                     unsigned char reply[10]; /* SOCKS5 atyp=1 reply */
228                     int atype, alen = 0;
229
230                     /*
231                      * Pre-fill reply packet.
232                      * In all cases, we set BND.{HOST,ADDR} to 0.0.0.0:0
233                      * (atyp=1) in the reply; if we succeed, we don't know
234                      * the right answers, and if we fail, they should be
235                      * ignored.
236                      */
237                     memset(reply, 0, lenof(reply));
238                     reply[0] = 5; /* VER */
239                     reply[3] = 1; /* ATYP = 1 (IPv4, 0.0.0.0:0) */
240
241                     if (pr->port < 6) continue;
242                     atype = (unsigned char)pr->hostname[3];
243                     if (atype == 1)    /* IPv4 address */
244                         alen = 4;
245                     if (atype == 4)    /* IPv6 address */
246                         alen = 16;
247                     if (atype == 3)    /* domain name has leading length */
248                         alen = 1 + (unsigned char)pr->hostname[4];
249                     if (pr->port < 6 + alen) continue;
250                     if (pr->hostname[1] != 1 || pr->hostname[2] != 0) {
251                         /* Not CONNECT or reserved field nonzero - error */
252                         reply[1] = 1;   /* generic failure */
253                         sk_write(pr->s, reply, lenof(reply));
254                         pfd_close(pr->s);
255                         return 1;
256                     }
257                     /*
258                      * Now we have a viable connect request. Switch
259                      * on atype.
260                      */
261                     pr->port = GET_16BIT_MSB_FIRST(pr->hostname+4+alen);
262                     if (atype == 1) {
263                         /* REP=0 (success) already */
264                         sk_write(pr->s, reply, lenof(reply));
265                         sprintf(pr->hostname, "%d.%d.%d.%d",
266                                 (unsigned char)pr->hostname[4],
267                                 (unsigned char)pr->hostname[5],
268                                 (unsigned char)pr->hostname[6],
269                                 (unsigned char)pr->hostname[7]);
270                         goto connect;
271                     } else if (atype == 3) {
272                         /* REP=0 (success) already */
273                         sk_write(pr->s, reply, lenof(reply));
274                         memmove(pr->hostname, pr->hostname + 5, alen-1);
275                         pr->hostname[alen-1] = '\0';
276                         goto connect;
277                     } else {
278                         /*
279                          * Unknown address type. (FIXME: support IPv6!)
280                          */
281                         reply[1] = 8;   /* atype not supported */
282                         sk_write(pr->s, reply, lenof(reply));
283                         pfd_close(pr->s);
284                         return 1;                       
285                     }
286                 }
287             }
288             
289             /*
290              * If we get here without either having done `continue'
291              * or `goto connect', it must be because there is no
292              * sensible interpretation of what's in our buffer. So
293              * close the connection rudely.
294              */
295             pfd_close(pr->s);
296             return 1;
297         }
298         return 1;
299
300         /*
301          * We come here when we're ready to make an actual
302          * connection.
303          */
304         connect:
305
306         pr->c = new_sock_channel(pr->backhandle, pr->s);
307         if (pr->c == NULL) {
308             pfd_close(pr->s);
309             return 1;
310         } else {
311             /* asks to forward to the specified host/port for this */
312             ssh_send_port_open(pr->c, pr->hostname, pr->port, "forwarding");
313         }
314         pr->dynamic = 0;
315
316         /*
317          * Now freeze the socket until the SSH server confirms the
318          * connection.
319          */
320         sk_set_frozen(pr->s, 1);
321         /*
322          * If there's any data remaining in our current buffer,
323          * save it to be sent on pfd_confirm().
324          */
325         if (len > 0) {
326             pr->buffer = snewn(len, char);
327             memcpy(pr->buffer, data, len);
328             pr->buflen = len;
329         }
330     }
331     if (pr->ready) {
332         if (sshfwd_write(pr->c, data, len) > 0) {
333             pr->throttled = 1;
334             sk_set_frozen(pr->s, 1);
335         }
336     }
337     return 1;
338 }
339
340 static void pfd_sent(Plug plug, int bufsize)
341 {
342     struct PFwdPrivate *pr = (struct PFwdPrivate *) plug;
343
344     if (pr->c)
345         sshfwd_unthrottle(pr->c, bufsize);
346 }
347
348 /*
349  * Called when receiving a PORT OPEN from the server
350  */
351 const char *pfd_newconnect(Socket *s, char *hostname, int port,
352                            void *c, const Config *cfg)
353 {
354     static const struct plug_function_table fn_table = {
355         pfd_closing,
356         pfd_receive,
357         pfd_sent,
358         NULL
359     };
360
361     SockAddr addr;
362     const char *err;
363     char *dummy_realhost;
364     struct PFwdPrivate *pr;
365
366     /*
367      * Try to find host.
368      */
369     addr = name_lookup(hostname, port, &dummy_realhost, cfg);
370     if ((err = sk_addr_error(addr)) != NULL) {
371         sk_addr_free(addr);
372         return err;
373     }
374
375     /*
376      * Open socket.
377      */
378     pr = snew(struct PFwdPrivate);
379     pr->buffer = NULL;
380     pr->fn = &fn_table;
381     pr->throttled = pr->throttle_override = 0;
382     pr->ready = 1;
383     pr->c = c;
384     pr->backhandle = NULL;             /* we shouldn't need this */
385     pr->dynamic = 0;
386
387     pr->s = *s = new_connection(addr, dummy_realhost, port,
388                                 0, 1, 0, (Plug) pr, cfg);
389     if ((err = sk_socket_error(*s)) != NULL) {
390         sfree(pr);
391         return err;
392     }
393
394     sk_set_private_ptr(*s, pr);
395     return NULL;
396 }
397
398 /*
399  called when someone connects to the local port
400  */
401
402 static int pfd_accepting(Plug p, OSSocket sock)
403 {
404     static const struct plug_function_table fn_table = {
405         pfd_closing,
406         pfd_receive,
407         pfd_sent,
408         NULL
409     };
410     struct PFwdPrivate *pr, *org;
411     Socket s;
412     const char *err;
413
414     org = (struct PFwdPrivate *)p;
415     pr = snew(struct PFwdPrivate);
416     pr->buffer = NULL;
417     pr->fn = &fn_table;
418
419     pr->c = NULL;
420     pr->backhandle = org->backhandle;
421
422     pr->s = s = sk_register(sock, (Plug) pr);
423     if ((err = sk_socket_error(s)) != NULL) {
424         sfree(pr);
425         return err != NULL;
426     }
427
428     sk_set_private_ptr(s, pr);
429
430     pr->throttled = pr->throttle_override = 0;
431     pr->ready = 0;
432
433     if (org->dynamic) {
434         pr->dynamic = 1;
435         pr->port = 0;                  /* hostname buffer is so far empty */
436         sk_set_frozen(s, 0);           /* we want to receive SOCKS _now_! */
437     } else {
438         pr->dynamic = 0;
439         strcpy(pr->hostname, org->hostname);
440         pr->port = org->port;   
441         pr->c = new_sock_channel(org->backhandle, s);
442
443         if (pr->c == NULL) {
444             sfree(pr);
445             return 1;
446         } else {
447             /* asks to forward to the specified host/port for this */
448             ssh_send_port_open(pr->c, pr->hostname, pr->port, "forwarding");
449         }
450     }
451
452     return 0;
453 }
454
455
456 /* Add a new forwarding from port -> desthost:destport
457  sets up a listener on the local machine on (srcaddr:)port
458  */
459 const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
460                            int port, void *backhandle, const Config *cfg)
461 {
462     static const struct plug_function_table fn_table = {
463         pfd_closing,
464         pfd_receive,                   /* should not happen... */
465         pfd_sent,                      /* also should not happen */
466         pfd_accepting
467     };
468
469     const char *err;
470     struct PFwdPrivate *pr;
471     Socket s;
472
473     /*
474      * Open socket.
475      */
476     pr = snew(struct PFwdPrivate);
477     pr->buffer = NULL;
478     pr->fn = &fn_table;
479     pr->c = NULL;
480     if (desthost) {
481         strcpy(pr->hostname, desthost);
482         pr->port = destport;
483         pr->dynamic = 0;
484     } else
485         pr->dynamic = 1;
486     pr->throttled = pr->throttle_override = 0;
487     pr->ready = 0;
488     pr->backhandle = backhandle;
489
490     pr->s = s = new_listener(srcaddr, port, (Plug) pr,
491                              !cfg->lport_acceptall, cfg);
492     if ((err = sk_socket_error(s)) != NULL) {
493         sfree(pr);
494         return err;
495     }
496
497     sk_set_private_ptr(s, pr);
498
499     return NULL;
500 }
501
502 void pfd_close(Socket s)
503 {
504     struct PFwdPrivate *pr;
505
506     if (!s)
507         return;
508
509     pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
510
511     sfree(pr->buffer);
512     sfree(pr);
513
514     sk_close(s);
515 }
516
517 void pfd_unthrottle(Socket s)
518 {
519     struct PFwdPrivate *pr;
520     if (!s)
521         return;
522     pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
523
524     pr->throttled = 0;
525     sk_set_frozen(s, pr->throttled || pr->throttle_override);
526 }
527
528 void pfd_override_throttle(Socket s, int enable)
529 {
530     struct PFwdPrivate *pr;
531     if (!s)
532         return;
533     pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
534
535     pr->throttle_override = enable;
536     sk_set_frozen(s, pr->throttled || pr->throttle_override);
537 }
538
539 /*
540  * Called to send data down the raw connection.
541  */
542 int pfd_send(Socket s, char *data, int len)
543 {
544     if (s == NULL)
545         return 0;
546     return sk_write(s, data, len);
547 }
548
549
550 void pfd_confirm(Socket s)
551 {
552     struct PFwdPrivate *pr;
553
554     if (s == NULL)
555         return;
556
557     pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
558     pr->ready = 1;
559     sk_set_frozen(s, 0);
560     sk_write(s, NULL, 0);
561     if (pr->buffer) {
562         sshfwd_write(pr->c, pr->buffer, pr->buflen);
563         sfree(pr->buffer);
564         pr->buffer = NULL;
565     }
566 }