summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--canohost.c4
-rw-r--r--canohost.h4
-rw-r--r--channels.c52
-rw-r--r--channels.h4
-rw-r--r--clientloop.c4
-rw-r--r--readconf.c13
-rw-r--r--readconf.h4
-rw-r--r--serverloop.c9
-rw-r--r--ssh.c15
10 files changed, 88 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index cdcd1aced..d8f8f2610 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,12 @@
4 [sftp.c] 4 [sftp.c]
5 Initialize a few variables to prevent spurious "may be used 5 Initialize a few variables to prevent spurious "may be used
6 uninitialized" warnings from newer gcc's. ok djm@ 6 uninitialized" warnings from newer gcc's. ok djm@
7 - djm@cvs.openbsd.org 2009/02/12 03:00:56
8 [canohost.c canohost.h channels.c channels.h clientloop.c readconf.c]
9 [readconf.h serverloop.c ssh.c]
10 support remote port forwarding with a zero listen port (-R0:...) to
11 dyamically allocate a listen port at runtime (this is actually
12 specified in rfc4254); bz#1003 ok markus@
7 13
820090212 1420090212
9 - (djm) [sshpty.c] bz#1419: OSX uses cloning ptys that automagically 15 - (djm) [sshpty.c] bz#1419: OSX uses cloning ptys that automagically
@@ -5130,5 +5136,5 @@
5130 OpenServer 6 and add osr5bigcrypt support so when someone migrates 5136 OpenServer 6 and add osr5bigcrypt support so when someone migrates
5131 passwords between UnixWare and OpenServer they will still work. OK dtucker@ 5137 passwords between UnixWare and OpenServer they will still work. OK dtucker@
5132 5138
5133$Id: ChangeLog,v 1.5186 2009/02/14 05:26:19 djm Exp $ 5139$Id: ChangeLog,v 1.5187 2009/02/14 05:28:21 djm Exp $
5134 5140
diff --git a/canohost.c b/canohost.c
index 42011fd0a..7138f48d0 100644
--- a/canohost.c
+++ b/canohost.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: canohost.c,v 1.63 2008/06/12 00:03:49 dtucker Exp $ */ 1/* $OpenBSD: canohost.c,v 1.64 2009/02/12 03:00:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -342,7 +342,7 @@ get_remote_name_or_ip(u_int utmp_len, int use_dns)
342 342
343/* Returns the local/remote port for the socket. */ 343/* Returns the local/remote port for the socket. */
344 344
345static int 345int
346get_sock_port(int sock, int local) 346get_sock_port(int sock, int local)
347{ 347{
348 struct sockaddr_storage from; 348 struct sockaddr_storage from;
diff --git a/canohost.h b/canohost.h
index e33e8941b..d9b41ffe5 100644
--- a/canohost.h
+++ b/canohost.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: canohost.h,v 1.9 2006/03/25 22:22:42 djm Exp $ */ 1/* $OpenBSD: canohost.h,v 1.10 2009/02/12 03:00:56 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -23,5 +23,7 @@ char *get_local_name(int);
23 23
24int get_remote_port(void); 24int get_remote_port(void);
25int get_local_port(void); 25int get_local_port(void);
26int get_sock_port(int, int);
27
26 28
27void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *); 29void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *);
diff --git a/channels.c b/channels.c
index 0b1c34c83..dea60ba24 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.294 2009/01/22 09:49:57 djm Exp $ */ 1/* $OpenBSD: channels.c,v 1.295 2009/02/12 03:00:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -2460,7 +2460,8 @@ channel_set_af(int af)
2460} 2460}
2461 2461
2462static int 2462static int
2463channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_port, 2463channel_setup_fwd_listener(int type, const char *listen_addr,
2464 u_short listen_port, int *allocated_listen_port,
2464 const char *host_to_connect, u_short port_to_connect, int gateway_ports) 2465 const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2465{ 2466{
2466 Channel *c; 2467 Channel *c;
@@ -2468,6 +2469,7 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
2468 struct addrinfo hints, *ai, *aitop; 2469 struct addrinfo hints, *ai, *aitop;
2469 const char *host, *addr; 2470 const char *host, *addr;
2470 char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 2471 char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2472 in_port_t *lport_p;
2471 2473
2472 host = (type == SSH_CHANNEL_RPORT_LISTENER) ? 2474 host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
2473 listen_addr : host_to_connect; 2475 listen_addr : host_to_connect;
@@ -2536,10 +2538,29 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
2536 } 2538 }
2537 return 0; 2539 return 0;
2538 } 2540 }
2539 2541 if (allocated_listen_port != NULL)
2542 *allocated_listen_port = 0;
2540 for (ai = aitop; ai; ai = ai->ai_next) { 2543 for (ai = aitop; ai; ai = ai->ai_next) {
2541 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) 2544 switch (ai->ai_family) {
2545 case AF_INET:
2546 lport_p = &((struct sockaddr_in *)ai->ai_addr)->
2547 sin_port;
2548 break;
2549 case AF_INET6:
2550 lport_p = &((struct sockaddr_in6 *)ai->ai_addr)->
2551 sin6_port;
2552 break;
2553 default:
2542 continue; 2554 continue;
2555 }
2556 /*
2557 * If allocating a port for -R forwards, then use the
2558 * same port for all address families.
2559 */
2560 if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&
2561 allocated_listen_port != NULL && *allocated_listen_port > 0)
2562 *lport_p = htons(*allocated_listen_port);
2563
2543 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), 2564 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
2544 strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 2565 strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
2545 error("channel_setup_fwd_listener: getnameinfo failed"); 2566 error("channel_setup_fwd_listener: getnameinfo failed");
@@ -2555,7 +2576,8 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
2555 2576
2556 channel_set_reuseaddr(sock); 2577 channel_set_reuseaddr(sock);
2557 2578
2558 debug("Local forwarding listening on %s port %s.", ntop, strport); 2579 debug("Local forwarding listening on %s port %s.",
2580 ntop, strport);
2559 2581
2560 /* Bind the socket to the address. */ 2582 /* Bind the socket to the address. */
2561 if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { 2583 if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
@@ -2574,6 +2596,19 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
2574 close(sock); 2596 close(sock);
2575 continue; 2597 continue;
2576 } 2598 }
2599
2600 /*
2601 * listen_port == 0 requests a dynamically allocated port -
2602 * record what we got.
2603 */
2604 if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&
2605 allocated_listen_port != NULL &&
2606 *allocated_listen_port == 0) {
2607 *allocated_listen_port = get_sock_port(sock, 1);
2608 debug("Allocated listen port %d",
2609 *allocated_listen_port);
2610 }
2611
2577 /* Allocate a channel number for the socket. */ 2612 /* Allocate a channel number for the socket. */
2578 c = channel_new("port listener", type, sock, sock, -1, 2613 c = channel_new("port listener", type, sock, sock, -1,
2579 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 2614 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
@@ -2616,17 +2651,18 @@ channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,
2616 const char *host_to_connect, u_short port_to_connect, int gateway_ports) 2651 const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2617{ 2652{
2618 return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, 2653 return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2619 listen_host, listen_port, host_to_connect, port_to_connect, 2654 listen_host, listen_port, NULL, host_to_connect, port_to_connect,
2620 gateway_ports); 2655 gateway_ports);
2621} 2656}
2622 2657
2623/* protocol v2 remote port fwd, used by sshd */ 2658/* protocol v2 remote port fwd, used by sshd */
2624int 2659int
2625channel_setup_remote_fwd_listener(const char *listen_address, 2660channel_setup_remote_fwd_listener(const char *listen_address,
2626 u_short listen_port, int gateway_ports) 2661 u_short listen_port, int *allocated_listen_port, int gateway_ports)
2627{ 2662{
2628 return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, 2663 return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER,
2629 listen_address, listen_port, NULL, 0, gateway_ports); 2664 listen_address, listen_port, allocated_listen_port,
2665 NULL, 0, gateway_ports);
2630} 2666}
2631 2667
2632/* 2668/*
diff --git a/channels.h b/channels.h
index 19fee769c..1488ed7e5 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.h,v 1.97 2009/01/22 09:46:01 djm Exp $ */ 1/* $OpenBSD: channels.h,v 1.98 2009/02/12 03:00:56 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -245,7 +245,7 @@ int channel_request_remote_forwarding(const char *, u_short,
245int channel_setup_local_fwd_listener(const char *, u_short, 245int channel_setup_local_fwd_listener(const char *, u_short,
246 const char *, u_short, int); 246 const char *, u_short, int);
247void channel_request_rforward_cancel(const char *host, u_short port); 247void channel_request_rforward_cancel(const char *host, u_short port);
248int channel_setup_remote_fwd_listener(const char *, u_short, int); 248int channel_setup_remote_fwd_listener(const char *, u_short, int *, int);
249int channel_cancel_rport_listener(const char *, u_short); 249int channel_cancel_rport_listener(const char *, u_short);
250 250
251/* x11 forwarding */ 251/* x11 forwarding */
diff --git a/clientloop.c b/clientloop.c
index 1b5badb71..a2d2d1d07 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.208 2009/01/22 10:02:34 djm Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.209 2009/02/12 03:00:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -849,7 +849,7 @@ process_cmdline(void)
849 } 849 }
850 channel_request_rforward_cancel(cancel_host, cancel_port); 850 channel_request_rforward_cancel(cancel_host, cancel_port);
851 } else { 851 } else {
852 if (!parse_forward(&fwd, s, dynamic ? 1 : 0)) { 852 if (!parse_forward(&fwd, s, dynamic, remote)) {
853 logit("Bad forwarding specification."); 853 logit("Bad forwarding specification.");
854 goto out; 854 goto out;
855 } 855 }
diff --git a/readconf.c b/readconf.c
index 0a8be1400..53fc6c7ba 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: readconf.c,v 1.175 2009/01/22 10:02:34 djm Exp $ */ 1/* $OpenBSD: readconf.c,v 1.176 2009/02/12 03:00:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -735,7 +735,8 @@ parse_int:
735 } 735 }
736 736
737 if (parse_forward(&fwd, fwdarg, 737 if (parse_forward(&fwd, fwdarg,
738 opcode == oDynamicForward ? 1 : 0) == 0) 738 opcode == oDynamicForward ? 1 : 0,
739 opcode == oRemoteForward ? 1 : 0) == 0)
739 fatal("%.200s line %d: Bad forwarding specification.", 740 fatal("%.200s line %d: Bad forwarding specification.",
740 filename, linenum); 741 filename, linenum);
741 742
@@ -1220,7 +1221,7 @@ fill_default_options(Options * options)
1220 * returns number of arguments parsed or zero on error 1221 * returns number of arguments parsed or zero on error
1221 */ 1222 */
1222int 1223int
1223parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd) 1224parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1224{ 1225{
1225 int i; 1226 int i;
1226 char *p, *cp, *fwdarg[4]; 1227 char *p, *cp, *fwdarg[4];
@@ -1283,12 +1284,16 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd)
1283 goto fail_free; 1284 goto fail_free;
1284 } 1285 }
1285 1286
1286 if (fwd->listen_port <= 0) 1287 if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
1287 goto fail_free; 1288 goto fail_free;
1288 1289
1289 if (fwd->connect_host != NULL && 1290 if (fwd->connect_host != NULL &&
1290 strlen(fwd->connect_host) >= NI_MAXHOST) 1291 strlen(fwd->connect_host) >= NI_MAXHOST)
1291 goto fail_free; 1292 goto fail_free;
1293 if (fwd->listen_host != NULL &&
1294 strlen(fwd->listen_host) >= NI_MAXHOST)
1295 goto fail_free;
1296
1292 1297
1293 return (i); 1298 return (i);
1294 1299
diff --git a/readconf.h b/readconf.h
index d94d65890..8fb3a8528 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: readconf.h,v 1.77 2009/01/22 10:02:34 djm Exp $ */ 1/* $OpenBSD: readconf.h,v 1.78 2009/02/12 03:00:56 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -134,7 +134,7 @@ typedef struct {
134void initialize_options(Options *); 134void initialize_options(Options *);
135void fill_default_options(Options *); 135void fill_default_options(Options *);
136int read_config_file(const char *, const char *, Options *, int); 136int read_config_file(const char *, const char *, Options *, int);
137int parse_forward(Forward *, const char *, int); 137int parse_forward(Forward *, const char *, int, int);
138 138
139int 139int
140process_config_line(Options *, const char *, char *, const char *, int, int *); 140process_config_line(Options *, const char *, char *, const char *, int, int *);
diff --git a/serverloop.c b/serverloop.c
index 931779e30..6244ad71c 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: serverloop.c,v 1.155 2009/01/22 10:02:34 djm Exp $ */ 1/* $OpenBSD: serverloop.c,v 1.156 2009/02/12 03:00:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1095,7 +1095,7 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
1095{ 1095{
1096 char *rtype; 1096 char *rtype;
1097 int want_reply; 1097 int want_reply;
1098 int success = 0; 1098 int success = 0, allocated_listen_port = 0;
1099 1099
1100 rtype = packet_get_string(NULL); 1100 rtype = packet_get_string(NULL);
1101 want_reply = packet_get_char(); 1101 want_reply = packet_get_char();
@@ -1119,7 +1119,8 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
1119 if (!options.allow_tcp_forwarding || 1119 if (!options.allow_tcp_forwarding ||
1120 no_port_forwarding_flag 1120 no_port_forwarding_flag
1121#ifndef NO_IPPORT_RESERVED_CONCEPT 1121#ifndef NO_IPPORT_RESERVED_CONCEPT
1122 || (listen_port < IPPORT_RESERVED && pw->pw_uid != 0) 1122 || (listen_port != 0 &&
1123 listen_port < IPPORT_RESERVED && pw->pw_uid != 0)
1123#endif 1124#endif
1124 ) { 1125 ) {
1125 success = 0; 1126 success = 0;
@@ -1149,6 +1150,8 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
1149 if (want_reply) { 1150 if (want_reply) {
1150 packet_start(success ? 1151 packet_start(success ?
1151 SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); 1152 SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
1153 if (success && allocated_listen_port > 0)
1154 packet_put_int(allocated_listen_port);
1152 packet_send(); 1155 packet_send();
1153 packet_write_wait(); 1156 packet_write_wait();
1154 } 1157 }
diff --git a/ssh.c b/ssh.c
index 26f070f3e..9d43bb74f 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.323 2009/01/22 10:02:34 djm Exp $ */ 1/* $OpenBSD: ssh.c,v 1.324 2009/02/12 03:00:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -453,7 +453,7 @@ main(int ac, char **av)
453 break; 453 break;
454 454
455 case 'L': 455 case 'L':
456 if (parse_forward(&fwd, optarg, 0)) 456 if (parse_forward(&fwd, optarg, 0, 0))
457 add_local_forward(&options, &fwd); 457 add_local_forward(&options, &fwd);
458 else { 458 else {
459 fprintf(stderr, 459 fprintf(stderr,
@@ -464,7 +464,7 @@ main(int ac, char **av)
464 break; 464 break;
465 465
466 case 'R': 466 case 'R':
467 if (parse_forward(&fwd, optarg, 0)) { 467 if (parse_forward(&fwd, optarg, 0, 1)) {
468 add_remote_forward(&options, &fwd); 468 add_remote_forward(&options, &fwd);
469 } else { 469 } else {
470 fprintf(stderr, 470 fprintf(stderr,
@@ -475,7 +475,7 @@ main(int ac, char **av)
475 break; 475 break;
476 476
477 case 'D': 477 case 'D':
478 if (parse_forward(&fwd, optarg, 1)) { 478 if (parse_forward(&fwd, optarg, 1, 0)) {
479 add_local_forward(&options, &fwd); 479 add_local_forward(&options, &fwd);
480 } else { 480 } else {
481 fprintf(stderr, 481 fprintf(stderr,
@@ -837,9 +837,16 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
837{ 837{
838 Forward *rfwd = (Forward *)ctxt; 838 Forward *rfwd = (Forward *)ctxt;
839 839
840 /* XXX verbose() on failure? */
840 debug("remote forward %s for: listen %d, connect %s:%d", 841 debug("remote forward %s for: listen %d, connect %s:%d",
841 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", 842 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
842 rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); 843 rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
844 if (type == SSH2_MSG_REQUEST_SUCCESS && rfwd->listen_port == 0) {
845 logit("Allocated port %u for remote forward to %s:%d",
846 packet_get_int(),
847 rfwd->connect_host, rfwd->connect_port);
848 }
849
843 if (type == SSH2_MSG_REQUEST_FAILURE) { 850 if (type == SSH2_MSG_REQUEST_FAILURE) {
844 if (options.exit_on_forward_failure) 851 if (options.exit_on_forward_failure)
845 fatal("Error: remote port forwarding failed for " 852 fatal("Error: remote port forwarding failed for "