diff -u -r openssh-3.8p1/channels.c openssh-3.8p1-localbind/channels.c --- openssh-3.8p1/channels.c 2004-01-20 16:02:09.000000000 -0800 +++ openssh-3.8p1-localbind/channels.c 2004-08-05 12:55:16.101830360 -0700 @@ -86,6 +86,7 @@ * network (which might be behind a firewall). */ typedef struct { + char *listen_host; /* Address to listen on */ char *host_to_connect; /* Connect to 'host'. */ u_short port_to_connect; /* Connect to 'port'. */ u_short listen_port; /* Remote side should listen port number. */ @@ -2146,8 +2147,7 @@ char ntop[NI_MAXHOST], strport[NI_MAXSERV]; success = 0; - host = (type == SSH_CHANNEL_RPORT_LISTENER) ? - listen_addr : host_to_connect; + host = host_to_connect; if (host == NULL) { error("No forward host name."); @@ -2167,7 +2167,8 @@ hints.ai_flags = gateway_ports ? AI_PASSIVE : 0; hints.ai_socktype = SOCK_STREAM; snprintf(strport, sizeof strport, "%d", listen_port); - if (getaddrinfo(NULL, strport, &hints, &aitop) != 0) + if (getaddrinfo (listen_addr==NULL?NULL:strlen(listen_addr)>0?listen_addr:NULL, + strport, &hints, &aitop) != 0) packet_disconnect("getaddrinfo: fatal error"); for (ai = aitop; ai; ai = ai->ai_next) { @@ -2222,28 +2223,28 @@ success = 1; } if (success == 0) - error("channel_setup_fwd_listener: cannot listen to port: %d", - listen_port); + error("channel_setup_fwd_listener: cannot listen to port: %s/%d", + listen_addr == NULL ? "0.0.0.0" : listen_addr, listen_port); freeaddrinfo(aitop); return success; } /* protocol local port fwd, used by ssh (and sshd in v1) */ int -channel_setup_local_fwd_listener(u_short listen_port, +channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port, const char *host_to_connect, u_short port_to_connect, int gateway_ports) { return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, - NULL, listen_port, host_to_connect, port_to_connect, gateway_ports); + listen_host, listen_port, host_to_connect, port_to_connect, gateway_ports); } /* protocol v2 remote port fwd, used by sshd */ int channel_setup_remote_fwd_listener(const char *listen_address, - u_short listen_port, int gateway_ports) + u_short listen_port, const char *bind_address, int gateway_ports) { return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, - listen_address, listen_port, NULL, 0, gateway_ports); + bind_address, listen_port, listen_address, 0, gateway_ports); } /* @@ -2252,7 +2253,7 @@ */ void -channel_request_remote_forwarding(u_short listen_port, +channel_request_remote_forwarding(const char *listen_host, u_short listen_port, const char *host_to_connect, u_short port_to_connect) { int type, success = 0; @@ -2263,7 +2264,8 @@ /* Send the forward request to the remote side. */ if (compat20) { - const char *address_to_bind = "0.0.0.0"; + const char *address_to_bind = + listen_host == NULL ? "0.0.0.0" : listen_host; packet_start(SSH2_MSG_GLOBAL_REQUEST); packet_put_cstring("tcpip-forward"); packet_put_char(1); /* boolean: want reply */ @@ -2297,6 +2299,7 @@ } } if (success) { + permitted_opens[num_permitted_opens].listen_host = listen_host == NULL ? NULL : xstrdup(listen_host); permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect); permitted_opens[num_permitted_opens].port_to_connect = port_to_connect; permitted_opens[num_permitted_opens].listen_port = listen_port; @@ -2335,7 +2338,7 @@ #endif /* Initiate forwarding */ - channel_setup_local_fwd_listener(port, hostname, host_port, gateway_ports); + channel_setup_local_fwd_listener(NULL, port, hostname, host_port, gateway_ports); /* Free the argument string. */ xfree(hostname); diff -u -r openssh-3.8p1/channels.h openssh-3.8p1-localbind/channels.h --- openssh-3.8p1/channels.h 2003-10-01 23:17:00.000000000 -0700 +++ openssh-3.8p1-localbind/channels.h 2004-08-05 09:44:22.159094328 -0700 @@ -199,9 +199,9 @@ void channel_input_port_forward_request(int, int); int channel_connect_to(const char *, u_short); int channel_connect_by_listen_address(u_short); -void channel_request_remote_forwarding(u_short, const char *, u_short); -int channel_setup_local_fwd_listener(u_short, const char *, u_short, int); -int channel_setup_remote_fwd_listener(const char *, u_short, int); +void channel_request_remote_forwarding(const char *, u_short, const char *, u_short); +int channel_setup_local_fwd_listener(const char *, u_short, const char *, u_short, int); +int channel_setup_remote_fwd_listener(const char *, u_short, const char *, int); /* x11 forwarding */ diff -u -r openssh-3.8p1/clientloop.c openssh-3.8p1-localbind/clientloop.c --- openssh-3.8p1/clientloop.c 2004-08-05 08:59:57.478187000 -0700 +++ openssh-3.8p1-localbind/clientloop.c 2004-08-05 09:44:51.134689368 -0700 @@ -549,13 +549,13 @@ goto out; } if (local) { - if (channel_setup_local_fwd_listener(fwd_port, buf, + if (channel_setup_local_fwd_listener(NULL, fwd_port, buf, fwd_host_port, options.gateway_ports) < 0) { logit("Port forwarding failed."); goto out; } } else - channel_request_remote_forwarding(fwd_port, buf, + channel_request_remote_forwarding(NULL, fwd_port, buf, fwd_host_port); logit("Forwarding port."); out: diff -u -r openssh-3.8p1/misc.c openssh-3.8p1-localbind/misc.c --- openssh-3.8p1/misc.c 2003-11-03 01:07:14.000000000 -0800 +++ openssh-3.8p1-localbind/misc.c 2004-08-05 11:49:12.019462480 -0700 @@ -141,6 +141,19 @@ return (old); } +int strcount( char *str, char c ) +{ + int count = 0; + + if( str == NULL ) + return -1; + + while( *str != 0 && *str != ' ' && *str != '\t' ) + if( *(str++) == c ) + count++; + return count; +} + struct passwd * pwcopy(struct passwd *pw) { diff -u -r openssh-3.8p1/misc.h openssh-3.8p1-localbind/misc.h --- openssh-3.8p1/misc.h 2003-08-24 18:16:21.000000000 -0700 +++ openssh-3.8p1-localbind/misc.h 2004-08-05 11:02:08.916639344 -0700 @@ -14,6 +14,7 @@ char *chop(char *); char *strdelim(char **); +int strcount( char *, char ); void set_nonblock(int); void unset_nonblock(int); void set_nodelay(int); diff -u -r openssh-3.8p1/readconf.c openssh-3.8p1-localbind/readconf.c --- openssh-3.8p1/readconf.c 2004-08-05 08:59:24.775159000 -0700 +++ openssh-3.8p1-localbind/readconf.c 2004-08-05 12:53:24.203841440 -0700 @@ -203,8 +203,8 @@ */ void -add_local_forward(Options *options, u_short port, const char *host, - u_short host_port) +add_local_forward(Options *options, const char *listen_host, u_short port, + const char *host, u_short host_port) { Forward *fwd; #ifndef NO_IPPORT_RESERVED_CONCEPT @@ -215,6 +215,7 @@ if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); fwd = &options->local_forwards[options->num_local_forwards++]; + fwd->listen_host = listen_host == NULL ? NULL : xstrdup(listen_host); fwd->port = port; fwd->host = xstrdup(host); fwd->host_port = host_port; @@ -226,14 +227,15 @@ */ void -add_remote_forward(Options *options, u_short port, const char *host, - u_short host_port) +add_remote_forward(Options *options, const char *listen_host, u_short port, + const char *host, u_short host_port) { Forward *fwd; if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) fatal("Too many remote forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); fwd = &options->remote_forwards[options->num_remote_forwards++]; + fwd->listen_host = listen_host == NULL ? NULL : xstrdup(listen_host); fwd->port = port; fwd->host = xstrdup(host); fwd->host_port = host_port; @@ -281,11 +283,12 @@ char *line, const char *filename, int linenum, int *activep) { - char buf[256], *s, **charptr, *endofnumber, *keyword, *arg; + char buf[256], buf2[256], *s, **charptr, *endofnumber, *keyword, *arg; int opcode, *intptr, value; size_t len; u_short fwd_port, fwd_host_port; char sfwd_host_port[6]; + char sfwd_port[6]; /* Strip trailing whitespace */ for(len = strlen(line) - 1; len > 0; len--) { @@ -645,13 +648,32 @@ case oLocalForward: case oRemoteForward: + buf[0] = '\0'; + arg = strdelim(&s); if (!arg || *arg == '\0') fatal("%.200s line %d: Missing port argument.", filename, linenum); - if ((fwd_port = a2port(arg)) == 0) - fatal("%.200s line %d: Bad listen port.", - filename, linenum); + + int slash_count = strcount( arg, '/' ); + int colon_count = strcount( arg, ':' ); + + if( slash_count == 1 || colon_count == 1 ) + { + if (sscanf(arg, "%255[^:]:%5[0-9]", buf2, sfwd_port) != 2 && + sscanf(arg, "%255[^/]/%5[0-9]", buf2, sfwd_port) != 2) + fatal("%.200s line %d: Bad bind_address forwarding specification.", + filename, linenum); + if ((fwd_port = a2port(sfwd_port)) == 0) + fatal("%.200s line %d: Bad forwarding port.", + filename, linenum); + } else + { + buf2[0] = '\0'; + if ((fwd_port = a2port(arg)) == 0) + fatal("%.200s line %d: Bad listen port.", + filename, linenum); + } arg = strdelim(&s); if (!arg || *arg == '\0') fatal("%.200s line %d: Missing second argument.", @@ -665,10 +687,10 @@ filename, linenum); if (*activep) { if (opcode == oLocalForward) - add_local_forward(options, fwd_port, buf, + add_local_forward(options, strlen(buf2) > 0 ? buf2 : NULL, fwd_port, buf, fwd_host_port); else if (opcode == oRemoteForward) - add_remote_forward(options, fwd_port, buf, + add_remote_forward(options, strlen(buf2) > 0 ? buf2 : NULL, fwd_port, buf, fwd_host_port); } break; @@ -683,7 +705,7 @@ fatal("%.200s line %d: Badly formatted port number.", filename, linenum); if (*activep) - add_local_forward(options, fwd_port, "socks", 0); + add_local_forward(options, NULL, fwd_port, "socks", 0); break; case oClearAllForwardings: diff -u -r openssh-3.8p1/readconf.h openssh-3.8p1-localbind/readconf.h --- openssh-3.8p1/readconf.h 2004-08-05 08:59:24.776158000 -0700 +++ openssh-3.8p1-localbind/readconf.h 2004-08-05 09:56:20.538884000 -0700 @@ -21,6 +21,7 @@ /* Data structure for representing a forwarding request. */ typedef struct { + char *listen_host; /* Host to forward. */ u_short port; /* Port to forward. */ char *host; /* Host to connect. */ u_short host_port; /* Port to connect on host. */ @@ -113,7 +114,7 @@ int process_config_line(Options *, const char *, char *, const char *, int, int *); -void add_local_forward(Options *, u_short, const char *, u_short); -void add_remote_forward(Options *, u_short, const char *, u_short); +void add_local_forward(Options *, const char *, u_short, const char *, u_short); +void add_remote_forward(Options *, const char *, u_short, const char *, u_short); #endif /* READCONF_H */ diff -u -r openssh-3.8p1/serverloop.c openssh-3.8p1-localbind/serverloop.c --- openssh-3.8p1/serverloop.c 2004-01-20 16:02:50.000000000 -0800 +++ openssh-3.8p1-localbind/serverloop.c 2004-08-05 12:27:29.649169672 -0700 @@ -988,7 +988,7 @@ } else { /* Start listening on the port */ success = channel_setup_remote_fwd_listener( - listen_address, listen_port, options.gateway_ports); + listen_address, listen_port, !strcmp(listen_address,"0.0.0.0")?NULL:listen_address, options.gateway_ports); } xfree(listen_address); } diff -u -r openssh-3.8p1/ssh.c openssh-3.8p1-localbind/ssh.c --- openssh-3.8p1/ssh.c 2003-12-16 21:33:11.000000000 -0800 +++ openssh-3.8p1-localbind/ssh.c 2004-08-05 12:58:46.419857160 -0700 @@ -174,8 +174,8 @@ fprintf(stderr, " -c cipher Select encryption algorithm\n"); fprintf(stderr, " -m macs Specify MAC algorithms for protocol version 2.\n"); fprintf(stderr, " -p port Connect to this port. Server must be on the same port.\n"); - fprintf(stderr, " -L listen-port:host:port Forward local port to remote address\n"); - fprintf(stderr, " -R listen-port:host:port Forward remote port to local address\n"); + fprintf(stderr, " -L [listen-host:]listen-port:host:port Forward local port to remote address\n"); + fprintf(stderr, " -R [listen-host:]listen-port:host:port Forward remote port to local address\n"); fprintf(stderr, " These cause %s to listen for connections on a port, and\n", __progname); fprintf(stderr, " forward them to the other side by connecting to host:port.\n"); fprintf(stderr, " -D port Enable dynamic application-level port forwarding.\n"); @@ -202,10 +202,10 @@ int main(int ac, char **av) { - int i, opt, exit_status; + int i, opt, exit_status, localbind = 0; u_short fwd_port, fwd_host_port; char sfwd_port[6], sfwd_host_port[6]; - char *p, *cp, *line, buf[256]; + char *p, *cp, *line, buf[256], buf2[256]; struct stat st; struct passwd *pw; int dummy; @@ -418,10 +418,16 @@ case 'L': case 'R': + buf[0] = 0; if (sscanf(optarg, "%5[0123456789]:%255[^:]:%5[0123456789]", sfwd_port, buf, sfwd_host_port) != 3 && sscanf(optarg, "%5[0123456789]/%255[^/]/%5[0123456789]", - sfwd_port, buf, sfwd_host_port) != 3) { + sfwd_port, buf, sfwd_host_port) != 3 && + (localbind = 1) && // Set localbind to TRUE + sscanf(optarg, "%255[^:]:%5[0123456789]:%255[^:]:%5[0123456789]", + buf2, sfwd_port, buf, sfwd_host_port) != 4 && + sscanf(optarg, "%255[^/]/%5[0123456789]/%255[^/]/%5[0123456789]", + buf2, sfwd_port, buf, sfwd_host_port) != 4) { fprintf(stderr, "Bad forwarding specification '%s'\n", optarg); @@ -435,11 +441,11 @@ exit(1); } if (opt == 'L') - add_local_forward(&options, fwd_port, buf, - fwd_host_port); + add_local_forward(&options, localbind ? buf2 : NULL, + fwd_port, buf, fwd_host_port); else if (opt == 'R') - add_remote_forward(&options, fwd_port, buf, - fwd_host_port); + add_remote_forward(&options, localbind ? buf2 : NULL, + fwd_port, buf, fwd_host_port); break; case 'D': @@ -449,7 +455,7 @@ optarg); exit(1); } - add_local_forward(&options, fwd_port, "socks", 0); + add_local_forward(&options, NULL, fwd_port, "socks", 0); break; case 'C': @@ -840,11 +846,13 @@ /* Initiate local TCP/IP port forwardings. */ for (i = 0; i < options.num_local_forwards; i++) { - debug("Connections to local port %d forwarded to remote address %.200s:%d", + debug("Connections to local port %.200s:%d forwarded to remote address %.200s:%d", + options.local_forwards[i].listen_host, options.local_forwards[i].port, options.local_forwards[i].host, options.local_forwards[i].host_port); success += channel_setup_local_fwd_listener( + options.local_forwards[i].listen_host, options.local_forwards[i].port, options.local_forwards[i].host, options.local_forwards[i].host_port, @@ -855,11 +863,13 @@ /* Initiate remote TCP/IP port forwardings. */ for (i = 0; i < options.num_remote_forwards; i++) { - debug("Connections to remote port %d forwarded to local address %.200s:%d", + debug("Connections to remote port %.200s:%d forwarded to local address %.200s:%d", + options.remote_forwards[i].listen_host, options.remote_forwards[i].port, options.remote_forwards[i].host, options.remote_forwards[i].host_port); channel_request_remote_forwarding( + options.remote_forwards[i].listen_host, options.remote_forwards[i].port, options.remote_forwards[i].host, options.remote_forwards[i].host_port);