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