1 /*
2  * SSH port forwarding.
3  */
4 
5 #include <assert.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 
9 #include "putty.h"
10 #include "ssh.h"
11 #include "sshchan.h"
12 
13 /*
14  * Enumeration of values that live in the 'socks_state' field of
15  * struct PortForwarding.
16  */
17 typedef enum {
18     SOCKS_NONE, /* direct connection (no SOCKS, or SOCKS already done) */
19     SOCKS_INITIAL,       /* don't know if we're SOCKS 4 or 5 yet */
20     SOCKS_4,             /* expect a SOCKS 4 (or 4A) connection message */
21     SOCKS_5_INITIAL,     /* expect a SOCKS 5 preliminary message */
22     SOCKS_5_CONNECT      /* expect a SOCKS 5 connection message */
23 } SocksState;
24 
25 typedef struct PortForwarding {
26     SshChannel *c;         /* channel structure held by SSH connection layer */
27     ConnectionLayer *cl;   /* the connection layer itself */
28     /* Note that ssh need not be filled in if c is non-NULL */
29     Socket *s;
30     bool input_wanted;
31     bool ready;
32     SocksState socks_state;
33     /*
34      * `hostname' and `port' are the real hostname and port, once
35      * we know what we're connecting to.
36      */
37     char *hostname;
38     int port;
39     /*
40      * `socksbuf' is the buffer we use to accumulate the initial SOCKS
41      * segment of the incoming data, plus anything after that that we
42      * receive before we're ready to send data to the SSH server.
43      */
44     strbuf *socksbuf;
45     size_t socksbuf_consumed;
46 
47     Plug plug;
48     Channel chan;
49 } PortForwarding;
50 
51 struct PortListener {
52     ConnectionLayer *cl;
53     Socket *s;
54     bool is_dynamic;
55     /*
56      * `hostname' and `port' are the real hostname and port, for
57      * ordinary forwardings.
58      */
59     char *hostname;
60     int port;
61 
62     Plug plug;
63 };
64 
new_portfwd_state(void)65 static struct PortForwarding *new_portfwd_state(void)
66 {
67     struct PortForwarding *pf = snew(struct PortForwarding);
68     pf->hostname = NULL;
69     pf->socksbuf = NULL;
70     return pf;
71 }
72 
free_portfwd_state(struct PortForwarding * pf)73 static void free_portfwd_state(struct PortForwarding *pf)
74 {
75     if (!pf)
76         return;
77     sfree(pf->hostname);
78     if (pf->socksbuf)
79         strbuf_free(pf->socksbuf);
80     sfree(pf);
81 }
82 
new_portlistener_state(void)83 static struct PortListener *new_portlistener_state(void)
84 {
85     struct PortListener *pl = snew(struct PortListener);
86     pl->hostname = NULL;
87     return pl;
88 }
89 
free_portlistener_state(struct PortListener * pl)90 static void free_portlistener_state(struct PortListener *pl)
91 {
92     if (!pl)
93         return;
94     sfree(pl->hostname);
95     sfree(pl);
96 }
97 
pfd_log(Plug * plug,PlugLogType type,SockAddr * addr,int port,const char * error_msg,int error_code)98 static void pfd_log(Plug *plug, PlugLogType type, SockAddr *addr, int port,
99                     const char *error_msg, int error_code)
100 {
101     /* we have to dump these since we have no interface to logging.c */
102 }
103 
pfl_log(Plug * plug,PlugLogType type,SockAddr * addr,int port,const char * error_msg,int error_code)104 static void pfl_log(Plug *plug, PlugLogType type, SockAddr *addr, int port,
105                     const char *error_msg, int error_code)
106 {
107     /* we have to dump these since we have no interface to logging.c */
108 }
109 
110 static void pfd_close(struct PortForwarding *pf);
111 
pfd_closing(Plug * plug,const char * error_msg,int error_code,bool calling_back)112 static void pfd_closing(Plug *plug, const char *error_msg, int error_code,
113                         bool calling_back)
114 {
115     struct PortForwarding *pf =
116         container_of(plug, struct PortForwarding, plug);
117 
118     if (error_msg) {
119         /*
120          * Socket error. Slam the connection instantly shut.
121          */
122         if (pf->c) {
123             sshfwd_initiate_close(pf->c, error_msg);
124         } else {
125             /*
126              * We might not have an SSH channel, if a socket error
127              * occurred during SOCKS negotiation. If not, we must
128              * clean ourself up without sshfwd_initiate_close's call
129              * back to pfd_close.
130              */
131             pfd_close(pf);
132         }
133     } else {
134         /*
135          * Ordinary EOF received on socket. Send an EOF on the SSH
136          * channel.
137          */
138         if (pf->c)
139             sshfwd_write_eof(pf->c);
140     }
141 }
142 
143 static void pfl_terminate(struct PortListener *pl);
144 
pfl_closing(Plug * plug,const char * error_msg,int error_code,bool calling_back)145 static void pfl_closing(Plug *plug, const char *error_msg, int error_code,
146                         bool calling_back)
147 {
148     struct PortListener *pl = (struct PortListener *) plug;
149     pfl_terminate(pl);
150 }
151 
wrap_lportfwd_open(ConnectionLayer * cl,const char * hostname,int port,Socket * s,Channel * chan)152 static SshChannel *wrap_lportfwd_open(
153     ConnectionLayer *cl, const char *hostname, int port,
154     Socket *s, Channel *chan)
155 {
156     SocketPeerInfo *pi;
157     char *description;
158     SshChannel *toret;
159 
160     pi = sk_peer_info(s);
161     if (pi && pi->log_text) {
162         description = dupprintf("forwarding from %s", pi->log_text);
163     } else {
164         description = dupstr("forwarding");
165     }
166     toret = ssh_lportfwd_open(cl, hostname, port, description, pi, chan);
167     sk_free_peer_info(pi);
168 
169     sfree(description);
170     return toret;
171 }
172 
ipv4_to_string(unsigned ipv4)173 static char *ipv4_to_string(unsigned ipv4)
174 {
175     return dupprintf("%u.%u.%u.%u",
176                      (ipv4 >> 24) & 0xFF, (ipv4 >> 16) & 0xFF,
177                      (ipv4 >>  8) & 0xFF, (ipv4      ) & 0xFF);
178 }
179 
ipv6_to_string(ptrlen ipv6)180 static char *ipv6_to_string(ptrlen ipv6)
181 {
182     const unsigned char *addr = ipv6.ptr;
183     assert(ipv6.len == 16);
184     return dupprintf("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
185                      (unsigned)GET_16BIT_MSB_FIRST(addr + 0),
186                      (unsigned)GET_16BIT_MSB_FIRST(addr + 2),
187                      (unsigned)GET_16BIT_MSB_FIRST(addr + 4),
188                      (unsigned)GET_16BIT_MSB_FIRST(addr + 6),
189                      (unsigned)GET_16BIT_MSB_FIRST(addr + 8),
190                      (unsigned)GET_16BIT_MSB_FIRST(addr + 10),
191                      (unsigned)GET_16BIT_MSB_FIRST(addr + 12),
192                      (unsigned)GET_16BIT_MSB_FIRST(addr + 14));
193 }
194 
pfd_receive(Plug * plug,int urgent,const char * data,size_t len)195 static void pfd_receive(Plug *plug, int urgent, const char *data, size_t len)
196 {
197     struct PortForwarding *pf =
198         container_of(plug, struct PortForwarding, plug);
199 
200     if (len == 0)
201         return;
202 
203     if (pf->socks_state != SOCKS_NONE) {
204         BinarySource src[1];
205 
206         /*
207          * Store all the data we've got in socksbuf.
208          */
209         put_data(pf->socksbuf, data, len);
210 
211         /*
212          * Check the start of socksbuf to see if it's a valid and
213          * complete message in the SOCKS exchange.
214          */
215 
216         if (pf->socks_state == SOCKS_INITIAL) {
217             /* Preliminary: check the first byte of the data (which we
218              * _must_ have by now) to find out which SOCKS major
219              * version we're speaking. */
220             switch (pf->socksbuf->u[0]) {
221               case 4:
222                 pf->socks_state = SOCKS_4;
223                 break;
224               case 5:
225                 pf->socks_state = SOCKS_5_INITIAL;
226                 break;
227               default:
228                 pfd_close(pf);         /* unrecognised version */
229                 return;
230             }
231         }
232 
233         BinarySource_BARE_INIT(src, pf->socksbuf->u, pf->socksbuf->len);
234         get_data(src, pf->socksbuf_consumed);
235 
236         while (pf->socks_state != SOCKS_NONE) {
237             unsigned socks_version, message_type, reserved_byte;
238             unsigned reply_code, port, ipv4, method;
239             ptrlen methods;
240             const char *socks4_hostname;
241             strbuf *output;
242 
243             switch (pf->socks_state) {
244               case SOCKS_INITIAL:
245               case SOCKS_NONE:
246                 unreachable("These case values cannot appear");
247 
248               case SOCKS_4:
249                 /* SOCKS 4/4A connect message */
250                 socks_version = get_byte(src);
251                 message_type = get_byte(src);
252 
253                 if (get_err(src) == BSE_OUT_OF_DATA)
254                     return;
255                 if (socks_version == 4 && message_type == 1) {
256                     /* CONNECT message */
257                     bool name_based = false;
258 
259                     port = get_uint16(src);
260                     ipv4 = get_uint32(src);
261                     if (ipv4 > 0x00000000 && ipv4 < 0x00000100) {
262                         /*
263                          * Addresses in this range indicate the SOCKS 4A
264                          * extension to specify a hostname, which comes
265                          * after the username.
266                          */
267                         name_based = true;
268                     }
269                     get_asciz(src);        /* skip username */
270                     socks4_hostname = name_based ? get_asciz(src) : NULL;
271 
272                     if (get_err(src) == BSE_OUT_OF_DATA)
273                         return;
274                     if (get_err(src))
275                         goto socks4_reject;
276 
277                     pf->port = port;
278                     if (name_based) {
279                         pf->hostname = dupstr(socks4_hostname);
280                     } else {
281                         pf->hostname = ipv4_to_string(ipv4);
282                     }
283 
284                     output = strbuf_new();
285                     put_byte(output, 0);       /* reply version */
286                     put_byte(output, 90);      /* SOCKS 4 'request granted' */
287                     put_uint16(output, 0);     /* null port field */
288                     put_uint32(output, 0);     /* null address field */
289                     sk_write(pf->s, output->u, output->len);
290                     strbuf_free(output);
291 
292                     pf->socks_state = SOCKS_NONE;
293                     pf->socksbuf_consumed = src->pos;
294                     break;
295                 }
296 
297               socks4_reject:
298                 output = strbuf_new();
299                 put_byte(output, 0);       /* reply version */
300                 put_byte(output, 91);      /* SOCKS 4 'request rejected' */
301                 put_uint16(output, 0);     /* null port field */
302                 put_uint32(output, 0);     /* null address field */
303                 sk_write(pf->s, output->u, output->len);
304                 strbuf_free(output);
305                 pfd_close(pf);
306                 return;
307 
308               case SOCKS_5_INITIAL:
309                 /* SOCKS 5 initial method list */
310                 socks_version = get_byte(src);
311                 methods = get_pstring(src);
312 
313                 method = 0xFF;         /* means 'no usable method found' */
314                 {
315                     int i;
316                     for (i = 0; i < methods.len; i++) {
317                         if (((const unsigned char *)methods.ptr)[i] == 0 ) {
318                             method = 0;        /* no auth */
319                             break;
320                         }
321                     }
322                 }
323 
324                 if (get_err(src) == BSE_OUT_OF_DATA)
325                     return;
326                 if (get_err(src))
327                     method = 0xFF;
328 
329                 output = strbuf_new();
330                 put_byte(output, 5);       /* SOCKS version */
331                 put_byte(output, method);  /* selected auth method */
332                 sk_write(pf->s, output->u, output->len);
333                 strbuf_free(output);
334 
335                 if (method == 0xFF) {
336                     pfd_close(pf);
337                     return;
338                 }
339 
340                 pf->socks_state = SOCKS_5_CONNECT;
341                 pf->socksbuf_consumed = src->pos;
342                 break;
343 
344               case SOCKS_5_CONNECT:
345                 /* SOCKS 5 connect message */
346                 socks_version = get_byte(src);
347                 message_type = get_byte(src);
348                 reserved_byte = get_byte(src);
349 
350                 if (socks_version == 5 && message_type == 1 &&
351                     reserved_byte == 0) {
352 
353                     reply_code = 0;        /* success */
354 
355                     switch (get_byte(src)) {
356                       case 1:              /* IPv4 */
357                         pf->hostname = ipv4_to_string(get_uint32(src));
358                         break;
359                       case 4:              /* IPv6 */
360                         pf->hostname = ipv6_to_string(get_data(src, 16));
361                         break;
362                       case 3:              /* unresolved domain name */
363                         pf->hostname = mkstr(get_pstring(src));
364                         break;
365                       default:
366                         pf->hostname = NULL;
367                         reply_code = 8;    /* address type not supported */
368                         break;
369                     }
370 
371                     pf->port = get_uint16(src);
372                 } else {
373                     reply_code = 7;        /* command not supported */
374                 }
375 
376                 if (get_err(src) == BSE_OUT_OF_DATA)
377                     return;
378                 if (get_err(src))
379                     reply_code = 1;        /* general server failure */
380 
381                 output = strbuf_new();
382                 put_byte(output, 5);       /* SOCKS version */
383                 put_byte(output, reply_code);
384                 put_byte(output, 0);       /* reserved */
385                 put_byte(output, 1);       /* IPv4 address follows */
386                 put_uint32(output, 0);     /* bound IPv4 address (unused) */
387                 put_uint16(output, 0);     /* bound port number (unused) */
388                 sk_write(pf->s, output->u, output->len);
389                 strbuf_free(output);
390 
391                 if (reply_code != 0) {
392                     pfd_close(pf);
393                     return;
394                 }
395 
396                 pf->socks_state = SOCKS_NONE;
397                 pf->socksbuf_consumed = src->pos;
398                 break;
399             }
400         }
401 
402         /*
403          * We come here when we're ready to make an actual
404          * connection.
405          */
406 
407         /*
408          * Freeze the socket until the SSH server confirms the
409          * connection.
410          */
411         sk_set_frozen(pf->s, true);
412 
413         pf->c = wrap_lportfwd_open(pf->cl, pf->hostname, pf->port, pf->s,
414                                    &pf->chan);
415     }
416     if (pf->ready)
417         sshfwd_write(pf->c, data, len);
418 }
419 
pfd_sent(Plug * plug,size_t bufsize)420 static void pfd_sent(Plug *plug, size_t bufsize)
421 {
422     struct PortForwarding *pf =
423         container_of(plug, struct PortForwarding, plug);
424 
425     if (pf->c)
426         sshfwd_unthrottle(pf->c, bufsize);
427 }
428 
429 static const PlugVtable PortForwarding_plugvt = {
430     .log = pfd_log,
431     .closing = pfd_closing,
432     .receive = pfd_receive,
433     .sent = pfd_sent,
434 };
435 
436 static void pfd_chan_free(Channel *chan);
437 static void pfd_open_confirmation(Channel *chan);
438 static void pfd_open_failure(Channel *chan, const char *errtext);
439 static size_t pfd_send(
440     Channel *chan, bool is_stderr, const void *data, size_t len);
441 static void pfd_send_eof(Channel *chan);
442 static void pfd_set_input_wanted(Channel *chan, bool wanted);
443 static char *pfd_log_close_msg(Channel *chan);
444 
445 static const ChannelVtable PortForwarding_channelvt = {
446     .free = pfd_chan_free,
447     .open_confirmation = pfd_open_confirmation,
448     .open_failed = pfd_open_failure,
449     .send = pfd_send,
450     .send_eof = pfd_send_eof,
451     .set_input_wanted = pfd_set_input_wanted,
452     .log_close_msg = pfd_log_close_msg,
453     .want_close = chan_default_want_close,
454     .rcvd_exit_status = chan_no_exit_status,
455     .rcvd_exit_signal = chan_no_exit_signal,
456     .rcvd_exit_signal_numeric = chan_no_exit_signal_numeric,
457     .run_shell = chan_no_run_shell,
458     .run_command = chan_no_run_command,
459     .run_subsystem = chan_no_run_subsystem,
460     .enable_x11_forwarding = chan_no_enable_x11_forwarding,
461     .enable_agent_forwarding = chan_no_enable_agent_forwarding,
462     .allocate_pty = chan_no_allocate_pty,
463     .set_env = chan_no_set_env,
464     .send_break = chan_no_send_break,
465     .send_signal = chan_no_send_signal,
466     .change_window_size = chan_no_change_window_size,
467     .request_response = chan_no_request_response,
468 };
469 
portfwd_raw_new(ConnectionLayer * cl,Plug ** plug,bool start_ready)470 Channel *portfwd_raw_new(ConnectionLayer *cl, Plug **plug, bool start_ready)
471 {
472     struct PortForwarding *pf;
473 
474     pf = new_portfwd_state();
475     pf->plug.vt = &PortForwarding_plugvt;
476     pf->chan.initial_fixed_window_size = 0;
477     pf->chan.vt = &PortForwarding_channelvt;
478     pf->input_wanted = true;
479 
480     pf->c = NULL;
481 
482     pf->cl = cl;
483     pf->input_wanted = true;
484     pf->ready = start_ready;
485 
486     pf->socks_state = SOCKS_NONE;
487     pf->hostname = NULL;
488     pf->port = 0;
489 
490     *plug = &pf->plug;
491     return &pf->chan;
492 }
493 
portfwd_raw_free(Channel * pfchan)494 void portfwd_raw_free(Channel *pfchan)
495 {
496     struct PortForwarding *pf;
497     assert(pfchan->vt == &PortForwarding_channelvt);
498     pf = container_of(pfchan, struct PortForwarding, chan);
499     free_portfwd_state(pf);
500 }
501 
portfwd_raw_setup(Channel * pfchan,Socket * s,SshChannel * sc)502 void portfwd_raw_setup(Channel *pfchan, Socket *s, SshChannel *sc)
503 {
504     struct PortForwarding *pf;
505     assert(pfchan->vt == &PortForwarding_channelvt);
506     pf = container_of(pfchan, struct PortForwarding, chan);
507 
508     pf->s = s;
509     pf->c = sc;
510 }
511 
512 /*
513  called when someone connects to the local port
514  */
515 
pfl_accepting(Plug * p,accept_fn_t constructor,accept_ctx_t ctx)516 static int pfl_accepting(Plug *p, accept_fn_t constructor, accept_ctx_t ctx)
517 {
518     struct PortListener *pl = container_of(p, struct PortListener, plug);
519     struct PortForwarding *pf;
520     Channel *chan;
521     Plug *plug;
522     Socket *s;
523     const char *err;
524 
525     chan = portfwd_raw_new(pl->cl, &plug, false);
526     s = constructor(ctx, plug);
527     if ((err = sk_socket_error(s)) != NULL) {
528         portfwd_raw_free(chan);
529         return 1;
530     }
531 
532     pf = container_of(chan, struct PortForwarding, chan);
533 
534     if (pl->is_dynamic) {
535         pf->s = s;
536         pf->socks_state = SOCKS_INITIAL;
537         pf->socksbuf = strbuf_new();
538         pf->socksbuf_consumed = 0;
539         pf->port = 0;                  /* "hostname" buffer is so far empty */
540         sk_set_frozen(s, false);       /* we want to receive SOCKS _now_! */
541     } else {
542         pf->hostname = dupstr(pl->hostname);
543         pf->port = pl->port;
544         portfwd_raw_setup(
545             chan, s,
546             wrap_lportfwd_open(pl->cl, pf->hostname, pf->port, s, &pf->chan));
547     }
548 
549     return 0;
550 }
551 
552 static const PlugVtable PortListener_plugvt = {
553     .log = pfl_log,
554     .closing = pfl_closing,
555     .accepting = pfl_accepting,
556 };
557 
558 /*
559  * Add a new port-forwarding listener from srcaddr:port -> desthost:destport.
560  *
561  * desthost == NULL indicates dynamic SOCKS port forwarding.
562  *
563  * On success, returns NULL and fills in *pl_ret. On error, returns a
564  * dynamically allocated error message string.
565  */
pfl_listen(const char * desthost,int destport,const char * srcaddr,int port,ConnectionLayer * cl,Conf * conf,struct PortListener ** pl_ret,int address_family)566 static char *pfl_listen(const char *desthost, int destport,
567                         const char *srcaddr, int port,
568                         ConnectionLayer *cl, Conf *conf,
569                         struct PortListener **pl_ret, int address_family)
570 {
571     const char *err;
572     struct PortListener *pl;
573 
574     /*
575      * Open socket.
576      */
577     pl = *pl_ret = new_portlistener_state();
578     pl->plug.vt = &PortListener_plugvt;
579     if (desthost) {
580         pl->hostname = dupstr(desthost);
581         pl->port = destport;
582         pl->is_dynamic = false;
583     } else
584         pl->is_dynamic = true;
585     pl->cl = cl;
586 
587     pl->s = new_listener(srcaddr, port, &pl->plug,
588                          !conf_get_bool(conf, CONF_lport_acceptall),
589                          conf, address_family);
590     if ((err = sk_socket_error(pl->s)) != NULL) {
591         char *err_ret = dupstr(err);
592         sk_close(pl->s);
593         free_portlistener_state(pl);
594         *pl_ret = NULL;
595         return err_ret;
596     }
597 
598     return NULL;
599 }
600 
pfd_log_close_msg(Channel * chan)601 static char *pfd_log_close_msg(Channel *chan)
602 {
603     return dupstr("Forwarded port closed");
604 }
605 
pfd_close(struct PortForwarding * pf)606 static void pfd_close(struct PortForwarding *pf)
607 {
608     if (!pf)
609         return;
610 
611     sk_close(pf->s);
612     free_portfwd_state(pf);
613 }
614 
615 /*
616  * Terminate a listener.
617  */
pfl_terminate(struct PortListener * pl)618 static void pfl_terminate(struct PortListener *pl)
619 {
620     if (!pl)
621         return;
622 
623     sk_close(pl->s);
624     free_portlistener_state(pl);
625 }
626 
pfd_set_input_wanted(Channel * chan,bool wanted)627 static void pfd_set_input_wanted(Channel *chan, bool wanted)
628 {
629     assert(chan->vt == &PortForwarding_channelvt);
630     PortForwarding *pf = container_of(chan, PortForwarding, chan);
631     pf->input_wanted = wanted;
632     sk_set_frozen(pf->s, !pf->input_wanted);
633 }
634 
pfd_chan_free(Channel * chan)635 static void pfd_chan_free(Channel *chan)
636 {
637     assert(chan->vt == &PortForwarding_channelvt);
638     PortForwarding *pf = container_of(chan, PortForwarding, chan);
639     pfd_close(pf);
640 }
641 
642 /*
643  * Called to send data down the raw connection.
644  */
pfd_send(Channel * chan,bool is_stderr,const void * data,size_t len)645 static size_t pfd_send(
646     Channel *chan, bool is_stderr, const void *data, size_t len)
647 {
648     assert(chan->vt == &PortForwarding_channelvt);
649     PortForwarding *pf = container_of(chan, PortForwarding, chan);
650     return sk_write(pf->s, data, len);
651 }
652 
pfd_send_eof(Channel * chan)653 static void pfd_send_eof(Channel *chan)
654 {
655     assert(chan->vt == &PortForwarding_channelvt);
656     PortForwarding *pf = container_of(chan, PortForwarding, chan);
657     sk_write_eof(pf->s);
658 }
659 
pfd_open_confirmation(Channel * chan)660 static void pfd_open_confirmation(Channel *chan)
661 {
662     assert(chan->vt == &PortForwarding_channelvt);
663     PortForwarding *pf = container_of(chan, PortForwarding, chan);
664 
665     pf->ready = true;
666     sk_set_frozen(pf->s, false);
667     sk_write(pf->s, NULL, 0);
668     if (pf->socksbuf) {
669         sshfwd_write(pf->c, pf->socksbuf->u + pf->socksbuf_consumed,
670                      pf->socksbuf->len - pf->socksbuf_consumed);
671         strbuf_free(pf->socksbuf);
672         pf->socksbuf = NULL;
673     }
674 }
675 
pfd_open_failure(Channel * chan,const char * errtext)676 static void pfd_open_failure(Channel *chan, const char *errtext)
677 {
678     assert(chan->vt == &PortForwarding_channelvt);
679     PortForwarding *pf = container_of(chan, PortForwarding, chan);
680 
681     logeventf(pf->cl->logctx,
682               "Forwarded connection refused by remote%s%s",
683               errtext ? ": " : "", errtext ? errtext : "");
684 }
685 
686 /* ----------------------------------------------------------------------
687  * Code to manage the complete set of currently active port
688  * forwardings, and update it from Conf.
689  */
690 
691 struct PortFwdRecord {
692     enum { DESTROY, KEEP, CREATE } status;
693     int type;
694     unsigned sport, dport;
695     char *saddr, *daddr;
696     char *sserv, *dserv;
697     struct ssh_rportfwd *remote;
698     int addressfamily;
699     struct PortListener *local;
700 };
701 
pfr_cmp(void * av,void * bv)702 static int pfr_cmp(void *av, void *bv)
703 {
704     PortFwdRecord *a = (PortFwdRecord *) av;
705     PortFwdRecord *b = (PortFwdRecord *) bv;
706     int i;
707     if (a->type > b->type)
708         return +1;
709     if (a->type < b->type)
710         return -1;
711     if (a->addressfamily > b->addressfamily)
712         return +1;
713     if (a->addressfamily < b->addressfamily)
714         return -1;
715     if ( (i = nullstrcmp(a->saddr, b->saddr)) != 0)
716         return i < 0 ? -1 : +1;
717     if (a->sport > b->sport)
718         return +1;
719     if (a->sport < b->sport)
720         return -1;
721     if (a->type != 'D') {
722         if ( (i = nullstrcmp(a->daddr, b->daddr)) != 0)
723             return i < 0 ? -1 : +1;
724         if (a->dport > b->dport)
725             return +1;
726         if (a->dport < b->dport)
727             return -1;
728     }
729     return 0;
730 }
731 
pfr_free(PortFwdRecord * pfr)732 static void pfr_free(PortFwdRecord *pfr)
733 {
734     /* Dispose of any listening socket. */
735     if (pfr->local)
736         pfl_terminate(pfr->local);
737 
738     sfree(pfr->saddr);
739     sfree(pfr->daddr);
740     sfree(pfr->sserv);
741     sfree(pfr->dserv);
742     sfree(pfr);
743 }
744 
745 struct PortFwdManager {
746     ConnectionLayer *cl;
747     Conf *conf;
748     tree234 *forwardings;
749 };
750 
portfwdmgr_new(ConnectionLayer * cl)751 PortFwdManager *portfwdmgr_new(ConnectionLayer *cl)
752 {
753     PortFwdManager *mgr = snew(PortFwdManager);
754 
755     mgr->cl = cl;
756     mgr->conf = NULL;
757     mgr->forwardings = newtree234(pfr_cmp);
758 
759     return mgr;
760 }
761 
portfwdmgr_close(PortFwdManager * mgr,PortFwdRecord * pfr)762 void portfwdmgr_close(PortFwdManager *mgr, PortFwdRecord *pfr)
763 {
764     PortFwdRecord *realpfr = del234(mgr->forwardings, pfr);
765     if (realpfr == pfr)
766         pfr_free(pfr);
767 }
768 
portfwdmgr_close_all(PortFwdManager * mgr)769 void portfwdmgr_close_all(PortFwdManager *mgr)
770 {
771     PortFwdRecord *pfr;
772 
773     while ((pfr = delpos234(mgr->forwardings, 0)) != NULL)
774         pfr_free(pfr);
775 }
776 
portfwdmgr_free(PortFwdManager * mgr)777 void portfwdmgr_free(PortFwdManager *mgr)
778 {
779     portfwdmgr_close_all(mgr);
780     freetree234(mgr->forwardings);
781     if (mgr->conf)
782         conf_free(mgr->conf);
783     sfree(mgr);
784 }
785 
portfwdmgr_config(PortFwdManager * mgr,Conf * conf)786 void portfwdmgr_config(PortFwdManager *mgr, Conf *conf)
787 {
788     PortFwdRecord *pfr;
789     int i;
790     char *key, *val;
791 
792     if (mgr->conf)
793         conf_free(mgr->conf);
794     mgr->conf = conf_copy(conf);
795 
796     /*
797      * Go through the existing port forwardings and tag them
798      * with status==DESTROY. Any that we want to keep will be
799      * re-enabled (status==KEEP) as we go through the
800      * configuration and find out which bits are the same as
801      * they were before.
802      */
803     for (i = 0; (pfr = index234(mgr->forwardings, i)) != NULL; i++)
804         pfr->status = DESTROY;
805 
806     for (val = conf_get_str_strs(conf, CONF_portfwd, NULL, &key);
807          val != NULL;
808          val = conf_get_str_strs(conf, CONF_portfwd, key, &key)) {
809         char *kp, *kp2, *vp, *vp2;
810         char address_family, type;
811         int sport, dport, sserv, dserv;
812         char *sports, *dports, *saddr, *host;
813 
814         kp = key;
815 
816         address_family = 'A';
817         type = 'L';
818         if (*kp == 'A' || *kp == '4' || *kp == '6')
819             address_family = *kp++;
820         if (*kp == 'L' || *kp == 'R')
821             type = *kp++;
822 
823         if ((kp2 = host_strchr(kp, ':')) != NULL) {
824             /*
825              * There's a colon in the middle of the source port
826              * string, which means that the part before it is
827              * actually a source address.
828              */
829             char *saddr_tmp = dupprintf("%.*s", (int)(kp2 - kp), kp);
830             saddr = host_strduptrim(saddr_tmp);
831             sfree(saddr_tmp);
832             sports = kp2+1;
833         } else {
834             saddr = NULL;
835             sports = kp;
836         }
837         sport = atoi(sports);
838         sserv = 0;
839         if (sport == 0) {
840             sserv = 1;
841             sport = net_service_lookup(sports);
842             if (!sport) {
843                 logeventf(mgr->cl->logctx, "Service lookup failed for source"
844                           " port \"%s\"", sports);
845             }
846         }
847 
848         if (type == 'L' && !strcmp(val, "D")) {
849             /* dynamic forwarding */
850             host = NULL;
851             dports = NULL;
852             dport = -1;
853             dserv = 0;
854             type = 'D';
855         } else {
856             /* ordinary forwarding */
857             vp = val;
858             vp2 = vp + host_strcspn(vp, ":");
859             host = dupprintf("%.*s", (int)(vp2 - vp), vp);
860             if (*vp2)
861                 vp2++;
862             dports = vp2;
863             dport = atoi(dports);
864             dserv = 0;
865             if (dport == 0) {
866                 dserv = 1;
867                 dport = net_service_lookup(dports);
868                 if (!dport) {
869                     logeventf(mgr->cl->logctx,
870                               "Service lookup failed for destination"
871                               " port \"%s\"", dports);
872                 }
873             }
874         }
875 
876         if (sport && dport) {
877             /* Set up a description of the source port. */
878             pfr = snew(PortFwdRecord);
879             pfr->type = type;
880             pfr->saddr = saddr;
881             pfr->sserv = sserv ? dupstr(sports) : NULL;
882             pfr->sport = sport;
883             pfr->daddr = host;
884             pfr->dserv = dserv ? dupstr(dports) : NULL;
885             pfr->dport = dport;
886             pfr->local = NULL;
887             pfr->remote = NULL;
888             pfr->addressfamily = (address_family == '4' ? ADDRTYPE_IPV4 :
889                                   address_family == '6' ? ADDRTYPE_IPV6 :
890                                   ADDRTYPE_UNSPEC);
891 
892             PortFwdRecord *existing = add234(mgr->forwardings, pfr);
893             if (existing != pfr) {
894                 if (existing->status == DESTROY) {
895                     /*
896                      * We already have a port forwarding up and running
897                      * with precisely these parameters. Hence, no need
898                      * to do anything; simply re-tag the existing one
899                      * as KEEP.
900                      */
901                     existing->status = KEEP;
902                 }
903                 /*
904                  * Anything else indicates that there was a duplicate
905                  * in our input, which we'll silently ignore.
906                  */
907                 pfr_free(pfr);
908             } else {
909                 pfr->status = CREATE;
910             }
911         } else {
912             sfree(saddr);
913             sfree(host);
914         }
915     }
916 
917     /*
918      * Now go through and destroy any port forwardings which were
919      * not re-enabled.
920      */
921     for (i = 0; (pfr = index234(mgr->forwardings, i)) != NULL; i++) {
922         if (pfr->status == DESTROY) {
923             char *message;
924 
925             message = dupprintf("%s port forwarding from %s%s%d",
926                                 pfr->type == 'L' ? "local" :
927                                 pfr->type == 'R' ? "remote" : "dynamic",
928                                 pfr->saddr ? pfr->saddr : "",
929                                 pfr->saddr ? ":" : "",
930                                 pfr->sport);
931 
932             if (pfr->type != 'D') {
933                 char *msg2 = dupprintf("%s to %s:%d", message,
934                                        pfr->daddr, pfr->dport);
935                 sfree(message);
936                 message = msg2;
937             }
938 
939             logeventf(mgr->cl->logctx, "Cancelling %s", message);
940             sfree(message);
941 
942             /* pfr->remote or pfr->local may be NULL if setting up a
943              * forwarding failed. */
944             if (pfr->remote) {
945                 /*
946                  * Cancel the port forwarding at the server
947                  * end.
948                  *
949                  * Actually closing the listening port on the server
950                  * side may fail - because in SSH-1 there's no message
951                  * in the protocol to request it!
952                  *
953                  * Instead, we simply remove the record of the
954                  * forwarding from our local end, so that any
955                  * connections the server tries to make on it are
956                  * rejected.
957                  */
958                 ssh_rportfwd_remove(mgr->cl, pfr->remote);
959                 pfr->remote = NULL;
960             } else if (pfr->local) {
961                 pfl_terminate(pfr->local);
962                 pfr->local = NULL;
963             }
964 
965             delpos234(mgr->forwardings, i);
966             pfr_free(pfr);
967             i--;                       /* so we don't skip one in the list */
968         }
969     }
970 
971     /*
972      * And finally, set up any new port forwardings (status==CREATE).
973      */
974     for (i = 0; (pfr = index234(mgr->forwardings, i)) != NULL; i++) {
975         if (pfr->status == CREATE) {
976             char *sportdesc, *dportdesc;
977             sportdesc = dupprintf("%s%s%s%s%d%s",
978                                   pfr->saddr ? pfr->saddr : "",
979                                   pfr->saddr ? ":" : "",
980                                   pfr->sserv ? pfr->sserv : "",
981                                   pfr->sserv ? "(" : "",
982                                   pfr->sport,
983                                   pfr->sserv ? ")" : "");
984             if (pfr->type == 'D') {
985                 dportdesc = NULL;
986             } else {
987                 dportdesc = dupprintf("%s:%s%s%d%s",
988                                       pfr->daddr,
989                                       pfr->dserv ? pfr->dserv : "",
990                                       pfr->dserv ? "(" : "",
991                                       pfr->dport,
992                                       pfr->dserv ? ")" : "");
993             }
994 
995             if (pfr->type == 'L') {
996                 char *err = pfl_listen(pfr->daddr, pfr->dport,
997                                        pfr->saddr, pfr->sport,
998                                        mgr->cl, conf, &pfr->local,
999                                        pfr->addressfamily);
1000 
1001                 logeventf(mgr->cl->logctx,
1002                           "Local %sport %s forwarding to %s%s%s",
1003                           pfr->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
1004                           pfr->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
1005                           sportdesc, dportdesc,
1006                           err ? " failed: " : "", err ? err : "");
1007                 if (err)
1008                     sfree(err);
1009             } else if (pfr->type == 'D') {
1010                 char *err = pfl_listen(NULL, -1, pfr->saddr, pfr->sport,
1011                                        mgr->cl, conf, &pfr->local,
1012                                        pfr->addressfamily);
1013 
1014                 logeventf(mgr->cl->logctx,
1015                           "Local %sport %s SOCKS dynamic forwarding%s%s",
1016                           pfr->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
1017                           pfr->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
1018                           sportdesc,
1019                           err ? " failed: " : "", err ? err : "");
1020 
1021                 if (err)
1022                     sfree(err);
1023             } else {
1024                 const char *shost;
1025 
1026                 if (pfr->saddr) {
1027                     shost = pfr->saddr;
1028                 } else if (conf_get_bool(conf, CONF_rport_acceptall)) {
1029                     shost = "";
1030                 } else {
1031                     shost = "localhost";
1032                 }
1033 
1034                 pfr->remote = ssh_rportfwd_alloc(
1035                     mgr->cl, shost, pfr->sport, pfr->daddr, pfr->dport,
1036                     pfr->addressfamily, sportdesc, pfr, NULL);
1037 
1038                 if (!pfr->remote) {
1039                     logeventf(mgr->cl->logctx,
1040                               "Duplicate remote port forwarding to %s:%d",
1041                               pfr->daddr, pfr->dport);
1042                     pfr_free(pfr);
1043                 } else {
1044                     logeventf(mgr->cl->logctx, "Requesting remote port %s"
1045                               " forward to %s", sportdesc, dportdesc);
1046                 }
1047             }
1048             sfree(sportdesc);
1049             sfree(dportdesc);
1050         }
1051     }
1052 }
1053 
portfwdmgr_listen(PortFwdManager * mgr,const char * host,int port,const char * keyhost,int keyport,Conf * conf)1054 bool portfwdmgr_listen(PortFwdManager *mgr, const char *host, int port,
1055                        const char *keyhost, int keyport, Conf *conf)
1056 {
1057     PortFwdRecord *pfr;
1058 
1059     pfr = snew(PortFwdRecord);
1060     pfr->type = 'L';
1061     pfr->saddr = host ? dupstr(host) : NULL;
1062     pfr->daddr = keyhost ? dupstr(keyhost) : NULL;
1063     pfr->sserv = pfr->dserv = NULL;
1064     pfr->sport = port;
1065     pfr->dport = keyport;
1066     pfr->local = NULL;
1067     pfr->remote = NULL;
1068     pfr->addressfamily = ADDRTYPE_UNSPEC;
1069 
1070     PortFwdRecord *existing = add234(mgr->forwardings, pfr);
1071     if (existing != pfr) {
1072         /*
1073          * We had this record already. Return failure.
1074          */
1075         pfr_free(pfr);
1076         return false;
1077     }
1078 
1079     char *err = pfl_listen(keyhost, keyport, host, port,
1080                            mgr->cl, conf, &pfr->local, pfr->addressfamily);
1081     logeventf(mgr->cl->logctx,
1082               "%s on port %s:%d to forward to client%s%s",
1083               err ? "Failed to listen" : "Listening", host, port,
1084               err ? ": " : "", err ? err : "");
1085     if (err) {
1086         sfree(err);
1087         del234(mgr->forwardings, pfr);
1088         pfr_free(pfr);
1089         return false;
1090     }
1091 
1092     return true;
1093 }
1094 
portfwdmgr_unlisten(PortFwdManager * mgr,const char * host,int port)1095 bool portfwdmgr_unlisten(PortFwdManager *mgr, const char *host, int port)
1096 {
1097     PortFwdRecord pfr_key;
1098 
1099     pfr_key.type = 'L';
1100     /* Safe to cast the const away here, because it will only be used
1101      * by pfr_cmp, which won't write to the string */
1102     pfr_key.saddr = pfr_key.daddr = (char *)host;
1103     pfr_key.sserv = pfr_key.dserv = NULL;
1104     pfr_key.sport = pfr_key.dport = port;
1105     pfr_key.local = NULL;
1106     pfr_key.remote = NULL;
1107     pfr_key.addressfamily = ADDRTYPE_UNSPEC;
1108 
1109     PortFwdRecord *pfr = del234(mgr->forwardings, &pfr_key);
1110 
1111     if (!pfr)
1112         return false;
1113 
1114     logeventf(mgr->cl->logctx, "Closing listening port %s:%d", host, port);
1115 
1116     pfr_free(pfr);
1117     return true;
1118 }
1119 
1120 /*
1121  * Called when receiving a PORT OPEN from the server to make a
1122  * connection to a destination host.
1123  *
1124  * On success, returns NULL and fills in *pf_ret. On error, returns a
1125  * dynamically allocated error message string.
1126  */
portfwdmgr_connect(PortFwdManager * mgr,Channel ** chan_ret,char * hostname,int port,SshChannel * c,int addressfamily)1127 char *portfwdmgr_connect(PortFwdManager *mgr, Channel **chan_ret,
1128                          char *hostname, int port, SshChannel *c,
1129                          int addressfamily)
1130 {
1131     SockAddr *addr;
1132     const char *err;
1133     char *dummy_realhost = NULL;
1134     struct PortForwarding *pf;
1135 
1136     /*
1137      * Try to find host.
1138      */
1139     addr = name_lookup(hostname, port, &dummy_realhost, mgr->conf,
1140                        addressfamily, NULL, NULL);
1141     if ((err = sk_addr_error(addr)) != NULL) {
1142         char *err_ret = dupstr(err);
1143         sk_addr_free(addr);
1144         sfree(dummy_realhost);
1145         return err_ret;
1146     }
1147 
1148     /*
1149      * Open socket.
1150      */
1151     pf = new_portfwd_state();
1152     *chan_ret = &pf->chan;
1153     pf->plug.vt = &PortForwarding_plugvt;
1154     pf->chan.initial_fixed_window_size = 0;
1155     pf->chan.vt = &PortForwarding_channelvt;
1156     pf->input_wanted = true;
1157     pf->ready = true;
1158     pf->c = c;
1159     pf->cl = mgr->cl;
1160     pf->socks_state = SOCKS_NONE;
1161 
1162     pf->s = new_connection(addr, dummy_realhost, port,
1163                            false, true, false, false, &pf->plug, mgr->conf);
1164     sfree(dummy_realhost);
1165     if ((err = sk_socket_error(pf->s)) != NULL) {
1166         char *err_ret = dupstr(err);
1167         sk_close(pf->s);
1168         free_portfwd_state(pf);
1169         *chan_ret = NULL;
1170         return err_ret;
1171     }
1172 
1173     return NULL;
1174 }
1175