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