View | Details | Raw Unified | Return to bug 413 | Differences between
and this patch

Collapse All | Expand All

(-)auth-options.c (-5 / +8 lines)
Lines 217-223 Link Here
217
		}
217
		}
218
		cp = "permitopen=\"";
218
		cp = "permitopen=\"";
219
		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
219
		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
220
			char host[256], sport[6];
220
			char *host, *p;
221
			u_short port;
221
			u_short port;
222
			char *patterns = xmalloc(strlen(opts) + 1);
222
			char *patterns = xmalloc(strlen(opts) + 1);
223
223
Lines 243-250 Link Here
243
			}
243
			}
244
			patterns[i] = 0;
244
			patterns[i] = 0;
245
			opts++;
245
			opts++;
246
			if (sscanf(patterns, "%255[^:]:%5[0-9]", host, sport) != 2 &&
246
			p = patterns;
247
			    sscanf(patterns, "%255[^/]/%5[0-9]", host, sport) != 2) {
247
			host = hpdelim(&p);
248
			if (!host) {
248
				debug("%.100s, line %lu: Bad permitopen specification "
249
				debug("%.100s, line %lu: Bad permitopen specification "
249
				    "<%.100s>", file, linenum, patterns);
250
				    "<%.100s>", file, linenum, patterns);
250
				auth_debug_add("%.100s, line %lu: "
251
				auth_debug_add("%.100s, line %lu: "
Lines 252-260 Link Here
252
				xfree(patterns);
253
				xfree(patterns);
253
				goto bad_option;
254
				goto bad_option;
254
			}
255
			}
255
			if ((port = a2port(sport)) == 0) {
256
 			host = cleanhostname(host);
257
 			port = p ? a2port(p) : 0;
258
 			if (port == 0) {
256
				debug("%.100s, line %lu: Bad permitopen port <%.100s>",
259
				debug("%.100s, line %lu: Bad permitopen port <%.100s>",
257
				    file, linenum, sport);
260
 				    file, linenum, p ? p : "");
258
				auth_debug_add("%.100s, line %lu: "
261
				auth_debug_add("%.100s, line %lu: "
259
				    "Bad permitopen port", file, linenum);
262
				    "Bad permitopen port", file, linenum);
260
				xfree(patterns);
263
				xfree(patterns);
(-)channels.c (-9 / +37 lines)
Lines 2016-2023 Link Here
2016
	Channel *c;
2016
	Channel *c;
2017
	int success, sock, on = 1;
2017
	int success, sock, on = 1;
2018
	struct addrinfo hints, *ai, *aitop;
2018
	struct addrinfo hints, *ai, *aitop;
2019
	const char *host;
2019
	const char *host, *addr = NULL;
2020
	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2020
	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2021
	int wildcard = 0;
2021
2022
2022
	success = 0;
2023
	success = 0;
2023
	host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
2024
	host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
Lines 2033-2048 Link Here
2033
	}
2034
	}
2034
2035
2035
	/*
2036
	/*
2037
	 * Determine whether or not a port forward listens to loopback,
2038
	 * specified address or wildcard.
2039
	 */
2040
	if (gateway_ports) {
2041
		if (listen_addr == NULL || listen_addr[0] == '\0' ||
2042
		    strcmp(listen_addr, "*") == 0)
2043
				wildcard = 1;
2044
			else
2045
				addr = listen_addr;
2046
	} else if (type == SSH_CHANNEL_PORT_LISTENER) {
2047
		/* A client may override GatewayPorts with a wildcard */
2048
		if (listen_addr != NULL && strcmp(listen_addr, "*") == 0)
2049
			wildcard = 1;
2050
		else
2051
			addr = listen_addr;
2052
	}
2053
2054
	/*
2036
	 * getaddrinfo returns a loopback address if the hostname is
2055
	 * getaddrinfo returns a loopback address if the hostname is
2037
	 * set to NULL and hints.ai_flags is not AI_PASSIVE
2056
	 * set to NULL and hints.ai_flags is not AI_PASSIVE
2038
	 */
2057
	 */
2039
	memset(&hints, 0, sizeof(hints));
2058
	memset(&hints, 0, sizeof(hints));
2040
	hints.ai_family = IPv4or6;
2059
	hints.ai_family = IPv4or6;
2041
	hints.ai_flags = gateway_ports ? AI_PASSIVE : 0;
2060
	hints.ai_flags = wildcard ? AI_PASSIVE : 0;
2042
	hints.ai_socktype = SOCK_STREAM;
2061
	hints.ai_socktype = SOCK_STREAM;
2043
	snprintf(strport, sizeof strport, "%d", listen_port);
2062
	snprintf(strport, sizeof strport, "%d", listen_port);
2044
	if (getaddrinfo(NULL, strport, &hints, &aitop) != 0)
2063
	if (getaddrinfo(addr, strport, &hints, &aitop) != 0)
2045
		packet_disconnect("getaddrinfo: fatal error");
2064
		packet_disconnect("getaddrinfo: %.200s: fatal error",
2065
		    addr ? addr : "(NULL)");
2046
2066
2047
	for (ai = aitop; ai; ai = ai->ai_next) {
2067
	for (ai = aitop; ai; ai = ai->ai_next) {
2048
		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
2068
		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
Lines 2104-2114 Link Here
2104
2124
2105
/* protocol local port fwd, used by ssh (and sshd in v1) */
2125
/* protocol local port fwd, used by ssh (and sshd in v1) */
2106
int
2126
int
2107
channel_setup_local_fwd_listener(u_short listen_port,
2127
channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,
2108
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2128
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2109
{
2129
{
2110
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2130
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2111
	    NULL, listen_port, host_to_connect, port_to_connect, gateway_ports);
2131
	    listen_host, listen_port, host_to_connect, port_to_connect,
2132
	    gateway_ports);
2112
}
2133
}
2113
2134
2114
/* protocol v2 remote port fwd, used by sshd */
2135
/* protocol v2 remote port fwd, used by sshd */
Lines 2126-2132 Link Here
2126
 */
2147
 */
2127
2148
2128
void
2149
void
2129
channel_request_remote_forwarding(u_short listen_port,
2150
channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
2130
    const char *host_to_connect, u_short port_to_connect)
2151
    const char *host_to_connect, u_short port_to_connect)
2131
{
2152
{
2132
	int type, success = 0;
2153
	int type, success = 0;
Lines 2137-2143 Link Here
2137
2158
2138
	/* Send the forward request to the remote side. */
2159
	/* Send the forward request to the remote side. */
2139
	if (compat20) {
2160
	if (compat20) {
2140
		const char *address_to_bind = "0.0.0.0";
2161
		const char *address_to_bind;
2162
		if (listen_host == NULL)
2163
			address_to_bind = "127.0.0.1";
2164
		else if (listen_host[0] == '\0' || strcmp(listen_host, "*")==0)
2165
			address_to_bind = "0.0.0.0";
2166
		else
2167
			address_to_bind = listen_host;
2168
2141
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
2169
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
2142
		packet_put_cstring("tcpip-forward");
2170
		packet_put_cstring("tcpip-forward");
2143
		packet_put_char(1);			/* boolean: want reply */
2171
		packet_put_char(1);			/* boolean: want reply */
Lines 2205-2211 Link Here
2205
				  port);
2233
				  port);
2206
#endif
2234
#endif
2207
	/* Initiate forwarding */
2235
	/* Initiate forwarding */
2208
	channel_setup_local_fwd_listener(port, hostname, host_port, gateway_ports);
2236
	channel_setup_local_fwd_listener(NULL, port, hostname, host_port, gateway_ports);
2209
2237
2210
	/* Free the argument string. */
2238
	/* Free the argument string. */
2211
	xfree(hostname);
2239
	xfree(hostname);
(-)channels.h (-2 / +5 lines)
Lines 199-206 Link Here
199
void     channel_input_port_forward_request(int, int);
199
void     channel_input_port_forward_request(int, int);
200
int	 channel_connect_to(const char *, u_short);
200
int	 channel_connect_to(const char *, u_short);
201
int	 channel_connect_by_listen_address(u_short);
201
int	 channel_connect_by_listen_address(u_short);
202
void	 channel_request_remote_forwarding(u_short, const char *, u_short);
202
void	
203
int	 channel_setup_local_fwd_listener(u_short, const char *, u_short, int);
203
channel_request_remote_forwarding(const char *, u_short, const char *, u_short);
204
int
205
channel_setup_local_fwd_listener(const char *, u_short, const char *, u_short,
206
int);
204
int	 channel_setup_remote_fwd_listener(const char *, u_short, int);
207
int	 channel_setup_remote_fwd_listener(const char *, u_short, int);
205
208
206
/* x11 forwarding */
209
/* x11 forwarding */
(-)clientloop.c (-18 / +8 lines)
Lines 476-483 Link Here
476
{
476
{
477
	void (*handler)(int);
477
	void (*handler)(int);
478
	char *s, *cmd;
478
	char *s, *cmd;
479
	u_short fwd_port, fwd_host_port;
479
	Forward fwd;
480
	char buf[1024], sfwd_port[6], sfwd_host_port[6];
481
	int local = 0;
480
	int local = 0;
482
481
483
	leave_raw_mode();
482
	leave_raw_mode();
Lines 499-529 Link Here
499
		logit("Not supported for SSH protocol version 1.");
498
		logit("Not supported for SSH protocol version 1.");
500
		goto out;
499
		goto out;
501
	}
500
	}
502
	s += 2;
503
	while (*s && isspace(*s))
504
		s++;
505
501
506
	if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]",
502
	if ( !parse_forward(&fwd, (s+2))) {
507
	    sfwd_port, buf, sfwd_host_port) != 3 &&
508
	    sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]",
509
	    sfwd_port, buf, sfwd_host_port) != 3) {
510
		logit("Bad forwarding specification.");
503
		logit("Bad forwarding specification.");
511
		goto out;
504
		goto out;
512
	}
505
	}
513
	if ((fwd_port = a2port(sfwd_port)) == 0 ||
506
514
	    (fwd_host_port = a2port(sfwd_host_port)) == 0) {
515
		logit("Bad forwarding port(s).");
516
		goto out;
517
	}
518
	if (local) {
507
	if (local) {
519
		if (channel_setup_local_fwd_listener(fwd_port, buf,
508
		if (channel_setup_local_fwd_listener(fwd.listen_host,
520
		    fwd_host_port, options.gateway_ports) < 0) {
509
		    fwd.listen_port, fwd.connect_host, fwd.connect_port,
510
		    options.gateway_ports) < 0) {
521
			logit("Port forwarding failed.");
511
			logit("Port forwarding failed.");
522
			goto out;
512
			goto out;
523
		}
513
		}
524
	} else
514
	} else
525
		channel_request_remote_forwarding(fwd_port, buf,
515
		channel_request_remote_forwarding(fwd.listen_host,
526
		    fwd_host_port);
516
		    fwd.listen_port, fwd.connect_host, fwd.connect_port);
527
	logit("Forwarding port.");
517
	logit("Forwarding port.");
528
out:
518
out:
529
	signal(SIGINT, handler);
519
	signal(SIGINT, handler);
(-)misc.c (+45 lines)
Lines 269-274 Link Here
269
	return total;
269
	return total;
270
}
270
}
271
271
272
/* Search for next delimiter between hostnames/addresses and ports.
273
 * Argument may be modified (for termination).
274
 * Returns *cp if parsing succeeds.
275
 * *cp is set to the start of the next delimiter, if one was found.
276
 * If this is the last field, *cp is set to NULL.
277
 */
278
char *
279
hpdelim(char **cp)
280
{
281
	char *s, *old;
282
283
	if (!(cp && *cp))
284
		return NULL;
285
286
	old = s = *cp;
287
	if (*s == '[') {
288
		s = strchr(s, ']');
289
		if (!s)
290
			return NULL;
291
		else
292
			++s;
293
	} else {
294
		s = strpbrk(s, ":/");
295
		if (!s)
296
			s = *cp + strlen(*cp);	/* trailing null */
297
	}
298
299
	switch (*s) {
300
	case '\0':
301
		*cp = NULL;	/* no more fields*/
302
		break;
303
	
304
	case ':':
305
	case '/':
306
		*s = '\0';	/* terminate */
307
		*cp = s + 1;
308
		break;
309
	
310
	default:
311
		return NULL;
312
	}
313
314
	return old;
315
}
316
272
char *
317
char *
273
cleanhostname(char *host)
318
cleanhostname(char *host)
274
{
319
{
(-)misc.h (+1 lines)
Lines 18-23 Link Here
18
void	 unset_nonblock(int);
18
void	 unset_nonblock(int);
19
void	 set_nodelay(int);
19
void	 set_nodelay(int);
20
int	 a2port(const char *);
20
int	 a2port(const char *);
21
char	*hpdelim(char **);
21
char	*cleanhostname(char *);
22
char	*cleanhostname(char *);
22
char	*colon(char *);
23
char	*colon(char *);
23
long	 convtime(const char *);
24
long	 convtime(const char *);
(-)readconf.c (-33 / +112 lines)
Lines 205-225 Link Here
205
 */
205
 */
206
206
207
void
207
void
208
add_local_forward(Options *options, u_short port, const char *host,
208
add_local_forward(Options *options, const char *listen_host,
209
		  u_short host_port)
209
		u_short listen_port, const char *connect_host,
210
		u_short connect_port)
210
{
211
{
211
	Forward *fwd;
212
	Forward *fwd;
212
#ifndef NO_IPPORT_RESERVED_CONCEPT
213
#ifndef NO_IPPORT_RESERVED_CONCEPT
213
	extern uid_t original_real_uid;
214
	extern uid_t original_real_uid;
214
	if (port < IPPORT_RESERVED && original_real_uid != 0)
215
	if (listen_port < IPPORT_RESERVED && original_real_uid != 0)
215
		fatal("Privileged ports can only be forwarded by root.");
216
		fatal("Privileged ports can only be forwarded by root.");
216
#endif
217
#endif
217
	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
218
	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
218
		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
219
		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
219
	fwd = &options->local_forwards[options->num_local_forwards++];
220
	fwd = &options->local_forwards[options->num_local_forwards++];
220
	fwd->port = port;
221
	if (listen_host == NULL)
221
	fwd->host = xstrdup(host);
222
		fwd->listen_host = NULL;
222
	fwd->host_port = host_port;
223
	else
224
		fwd->listen_host = xstrdup(listen_host);
225
	fwd->listen_port = listen_port;
226
	fwd->connect_host = xstrdup(connect_host);
227
	fwd->connect_port = connect_port;
223
}
228
}
224
229
225
/*
230
/*
Lines 228-244 Link Here
228
 */
233
 */
229
234
230
void
235
void
231
add_remote_forward(Options *options, u_short port, const char *host,
236
add_remote_forward(Options *options, const char *listen_host,
232
		   u_short host_port)
237
		   u_short listen_port, const char *connect_host,
238
		   u_short connect_port)
233
{
239
{
234
	Forward *fwd;
240
	Forward *fwd;
235
	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
241
	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
236
		fatal("Too many remote forwards (max %d).",
242
		fatal("Too many remote forwards (max %d).",
237
		    SSH_MAX_FORWARDS_PER_DIRECTION);
243
		    SSH_MAX_FORWARDS_PER_DIRECTION);
238
	fwd = &options->remote_forwards[options->num_remote_forwards++];
244
	fwd = &options->remote_forwards[options->num_remote_forwards++];
239
	fwd->port = port;
245
	if (listen_host == NULL)
240
	fwd->host = xstrdup(host);
246
		fwd->listen_host = NULL;
241
	fwd->host_port = host_port;
247
	else
248
		fwd->listen_host = xstrdup(listen_host);
249
	fwd->listen_port = listen_port;
250
	fwd->connect_host = xstrdup(connect_host);
251
	fwd->connect_port = connect_port;
242
}
252
}
243
253
244
static void
254
static void
Lines 246-256 Link Here
246
{
256
{
247
	int i;
257
	int i;
248
258
249
	for (i = 0; i < options->num_local_forwards; i++)
259
	for (i = 0; i < options->num_local_forwards; i++) {
250
		xfree(options->local_forwards[i].host);
260
		xfree(options->local_forwards[i].listen_host);
261
		xfree(options->local_forwards[i].connect_host);
262
	}
251
	options->num_local_forwards = 0;
263
	options->num_local_forwards = 0;
252
	for (i = 0; i < options->num_remote_forwards; i++)
264
	for (i = 0; i < options->num_remote_forwards; i++) {
253
		xfree(options->remote_forwards[i].host);
265
		xfree(options->remote_forwards[i].listen_host);
266
		xfree(options->remote_forwards[i].connect_host);
267
	}
254
	options->num_remote_forwards = 0;
268
	options->num_remote_forwards = 0;
255
}
269
}
256
270
Lines 283-294 Link Here
283
		    char *line, const char *filename, int linenum,
297
		    char *line, const char *filename, int linenum,
284
		    int *activep)
298
		    int *activep)
285
{
299
{
286
	char buf[256], *s, **charptr, *endofnumber, *keyword, *arg;
300
	char *s, **charptr, *endofnumber, *keyword, *arg,
301
	    *arg2, fwdarg[256];
287
	int opcode, *intptr, value;
302
	int opcode, *intptr, value;
288
	size_t len;
303
	size_t len;
289
	u_short fwd_port, fwd_host_port;
290
	char sfwd_host_port[6];
291
	extern int IPv4or6;
304
	extern int IPv4or6;
305
	Forward fwd;
292
306
293
	/* Strip trailing whitespace */
307
	/* Strip trailing whitespace */
294
	for(len = strlen(line) - 1; len > 0; len--) {
308
	for(len = strlen(line) - 1; len > 0; len--) {
Lines 649-675 Link Here
649
		if (!arg || *arg == '\0')
663
		if (!arg || *arg == '\0')
650
			fatal("%.200s line %d: Missing port argument.",
664
			fatal("%.200s line %d: Missing port argument.",
651
			    filename, linenum);
665
			    filename, linenum);
652
		if ((fwd_port = a2port(arg)) == 0)
666
		arg2 = strdelim(&s);
653
			fatal("%.200s line %d: Bad listen port.",
667
		if (!arg2 || *arg2 == '\0')
654
			    filename, linenum);
655
		arg = strdelim(&s);
656
		if (!arg || *arg == '\0')
657
			fatal("%.200s line %d: Missing second argument.",
668
			fatal("%.200s line %d: Missing second argument.",
658
			    filename, linenum);
669
			    filename, linenum);
659
		if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 &&
670
660
		    sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
671
		/* construct a string for parse_forward */
672
		snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
673
674
		if (parse_forward(&fwd, fwdarg) == 0)
661
			fatal("%.200s line %d: Bad forwarding specification.",
675
			fatal("%.200s line %d: Bad forwarding specification.",
662
			    filename, linenum);
676
			    filename, linenum);
663
		if ((fwd_host_port = a2port(sfwd_host_port)) == 0)
677
		if (fwd.listen_port == 0)
678
			fatal("%.200s line %d: Bad listen port.",
679
			    filename, linenum);
680
		if (fwd.connect_port == 0)
664
			fatal("%.200s line %d: Bad forwarding port.",
681
			fatal("%.200s line %d: Bad forwarding port.",
665
			    filename, linenum);
682
			    filename, linenum);
683
666
		if (*activep) {
684
		if (*activep) {
667
			if (opcode == oLocalForward)
685
			if (opcode == oLocalForward)
668
				add_local_forward(options, fwd_port, buf,
686
				add_local_forward(options,
669
				    fwd_host_port);
687
				    fwd.listen_host, fwd.listen_port,
688
				    fwd.connect_host, fwd.connect_port);
670
			else if (opcode == oRemoteForward)
689
			else if (opcode == oRemoteForward)
671
				add_remote_forward(options, fwd_port, buf,
690
				add_remote_forward(options,
672
				    fwd_host_port);
691
				    fwd.listen_host, fwd.listen_port,
692
				    fwd.connect_host, fwd.connect_port);
673
		}
693
		}
674
		break;
694
		break;
675
695
Lines 678-689 Link Here
678
		if (!arg || *arg == '\0')
698
		if (!arg || *arg == '\0')
679
			fatal("%.200s line %d: Missing port argument.",
699
			fatal("%.200s line %d: Missing port argument.",
680
			    filename, linenum);
700
			    filename, linenum);
681
		fwd_port = a2port(arg);
701
		fwd.listen_port = 0;
682
		if (fwd_port == 0)
702
		fwd.listen_host = hpdelim(&arg);
703
		if (!fwd.listen_host)
704
			fatal("%.200s line %d: Bad forwarding specification.",
705
			    filename, linenum);
706
		if (arg) {
707
			fwd.listen_port = a2port(arg);
708
			fwd.listen_host = cleanhostname(fwd.listen_host);
709
		} else {
710
			fwd.listen_port = a2port(fwd.listen_host);
711
			fwd.listen_host = "";
712
		}
713
		if (fwd.listen_port == 0)
683
			fatal("%.200s line %d: Badly formatted port number.",
714
			fatal("%.200s line %d: Badly formatted port number.",
684
			    filename, linenum);
715
			    filename, linenum);
685
		if (*activep)
716
		if (*activep)
686
			add_local_forward(options, fwd_port, "socks4", 0);
717
			add_local_forward(options, fwd.listen_host,
718
			    fwd.listen_port, "socks4", 0);
687
		break;
719
		break;
688
720
689
	case oClearAllForwardings:
721
	case oClearAllForwardings:
Lines 985-988 Link Here
985
	/* options->hostname will be set in the main program if appropriate */
1017
	/* options->hostname will be set in the main program if appropriate */
986
	/* options->host_key_alias should not be set by default */
1018
	/* options->host_key_alias should not be set by default */
987
	/* options->preferred_authentications will be set in ssh */
1019
	/* options->preferred_authentications will be set in ssh */
1020
}
1021
1022
/*
1023
 * parse_forward
1024
 * parses a string containing a port forwarding specification of the form:
1025
 *	[listenhost:]listenport:connecthost:connectport
1026
 * returns number of arguments parsed or zero on error
1027
 */
1028
int
1029
parse_forward(Forward *fwd, const char *fwdspec)
1030
{
1031
	int i;
1032
	char *p, *cp, *fwdarg[4];
1033
1034
	cp = p = xstrdup(fwdspec);
1035
1036
	/* skip leading spaces */
1037
	while (*cp && isspace(*cp))
1038
		cp++;
1039
1040
	for (i = 0; i < 4; ++i)
1041
		if ( !(fwdarg[i] = hpdelim(&cp)) )
1042
			break;
1043
	switch(i) {
1044
	case 3:
1045
		fwd->listen_host = NULL;
1046
		fwd->listen_port = a2port(fwdarg[0]);
1047
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1048
		fwd->connect_port = a2port(fwdarg[2]);
1049
		break;
1050
1051
	case 4:
1052
		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1053
		fwd->listen_port = a2port(fwdarg[1]);
1054
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1055
		fwd->connect_port = a2port(fwdarg[3]);
1056
		break;
1057
	default:
1058
		i = 0; /* failure */
1059
	}
1060
1061
	xfree(p);
1062
1063
	if (fwd->listen_port == 0 && fwd->connect_port == 0)
1064
		i = 0;	/* failure */
1065
1066
	return(i);
988
}
1067
}
(-)readconf.h (-5 / +9 lines)
Lines 21-29 Link Here
21
/* Data structure for representing a forwarding request. */
21
/* Data structure for representing a forwarding request. */
22
22
23
typedef struct {
23
typedef struct {
24
	u_short	  port;		/* Port to forward. */
24
	char	 *listen_host;		/* Host (address) to listen on. */
25
	char	 *host;		/* Host to connect. */
25
	u_short	  listen_port;		/* Port to forward. */
26
	u_short	  host_port;	/* Port to connect on host. */
26
	char	 *connect_host;		/* Host to connect. */
27
	u_short	  connect_port;		/* Port to connect on connect_host. */
27
}       Forward;
28
}       Forward;
28
/* Data structure for representing option data. */
29
/* Data structure for representing option data. */
29
30
Lines 106-116 Link Here
106
void     initialize_options(Options *);
107
void     initialize_options(Options *);
107
void     fill_default_options(Options *);
108
void     fill_default_options(Options *);
108
int	 read_config_file(const char *, const char *, Options *);
109
int	 read_config_file(const char *, const char *, Options *);
110
int	 parse_forward(Forward *, const char *);
109
111
110
int
112
int
111
process_config_line(Options *, const char *, char *, const char *, int, int *);
113
process_config_line(Options *, const char *, char *, const char *, int, int *);
112
114
113
void	 add_local_forward(Options *, u_short, const char *, u_short);
115
void
114
void	 add_remote_forward(Options *, u_short, const char *, u_short);
116
add_local_forward(Options *, const char *, u_short, const char *, u_short);
117
void
118
add_remote_forward(Options *, const char *, u_short, const char *, u_short);
115
119
116
#endif				/* READCONF_H */
120
#endif				/* READCONF_H */
(-)servconf.c (-28 / +17 lines)
Lines 427-432 Link Here
427
	char *cp, **charptr, *arg, *p;
427
	char *cp, **charptr, *arg, *p;
428
	int *intptr, value, i, n;
428
	int *intptr, value, i, n;
429
	ServerOpCodes opcode;
429
	ServerOpCodes opcode;
430
	ushort port;
430
431
431
	cp = line;
432
	cp = line;
432
	arg = strdelim(&cp);
433
	arg = strdelim(&cp);
Lines 499-537 Link Here
499
500
500
	case sListenAddress:
501
	case sListenAddress:
501
		arg = strdelim(&cp);
502
		arg = strdelim(&cp);
502
		if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
503
		if (!arg || *arg == '\0')
503
			fatal("%s line %d: missing inet addr.",
504
			fatal("%s line %d: missing inet addr.",
504
			    filename, linenum);
505
			    filename, linenum);
505
		if (*arg == '[') {
506
		p = hpdelim(&arg);
506
			if ((p = strchr(arg, ']')) == NULL)
507
		if (!p)
507
				fatal("%s line %d: bad ipv6 inet addr usage.",
508
			fatal("%s line %d: bad inet addr:port usage.",
509
			    filename, linenum);
510
		p = cleanhostname(p);
511
		if (arg) {
512
			port = a2port(arg);
513
			if (port == 0) {
514
				fatal("%s line %d: bad port number.",
508
				    filename, linenum);
515
				    filename, linenum);
509
			arg++;
516
				/* NOTREACHED */
510
			memmove(p, p+1, strlen(p+1)+1);
517
			}
511
		} else if (((p = strchr(arg, ':')) == NULL) ||
518
		} else {
512
			    (strchr(p+1, ':') != NULL)) {
519
			port = 0;
513
			add_listen_addr(options, arg, 0);
514
			break;
515
		}
520
		}
516
		if (*p == ':') {
517
			u_short port;
518
521
519
			p++;
522
		add_listen_addr(options, p, port);
520
			if (*p == '\0')
523
521
				fatal("%s line %d: bad inet addr:port usage.",
522
				    filename, linenum);
523
			else {
524
				*(p-1) = '\0';
525
				if ((port = a2port(p)) == 0)
526
					fatal("%s line %d: bad port number.",
527
					    filename, linenum);
528
				add_listen_addr(options, arg, port);
529
			}
530
		} else if (*p == '\0')
531
			add_listen_addr(options, arg, 0);
532
		else
533
			fatal("%s line %d: bad inet addr usage.",
534
			    filename, linenum);
535
		break;
524
		break;
536
525
537
	case sHostKeyFile:
526
	case sHostKeyFile:
(-)ssh.1 (-14 / +22 lines)
Lines 61-69 Link Here
61
.Op Fl F Ar configfile
61
.Op Fl F Ar configfile
62
.Oo Fl L Xo
62
.Oo Fl L Xo
63
.Sm off
63
.Sm off
64
.Ar port :
64
.Ar [ listenhost : ]
65
.Ar listenport :
65
.Ar host :
66
.Ar host :
66
.Ar hostport
67
.Ar port
67
.Sm on
68
.Sm on
68
.Xc
69
.Xc
69
.Oc
70
.Oc
Lines 71-79 Link Here
71
.Bk -words
72
.Bk -words
72
.Oo Fl R Xo
73
.Oo Fl R Xo
73
.Sm off
74
.Sm off
74
.Ar port :
75
.Ar [ listenhost : ]
76
.Ar listenport :
75
.Ar host :
77
.Ar host :
76
.Ar hostport
78
.Ar port
77
.Sm on
79
.Sm on
78
.Xc
80
.Xc
79
.Oc
81
.Oc
Lines 606-651 Link Here
606
will be ignored.
608
will be ignored.
607
The default for the per-user configuration file is
609
The default for the per-user configuration file is
608
.Pa $HOME/.ssh/config .
610
.Pa $HOME/.ssh/config .
609
.It Fl L Ar port:host:hostport
611
.It Fl L Ar [listenhost:]listenport:host:port
610
Specifies that the given port on the local (client) host is to be
612
Specifies that the given port on the local (client) host is to be
611
forwarded to the given host and port on the remote side.
613
forwarded to the given host and port on the remote side.
612
This works by allocating a socket to listen to
614
This works by allocating a socket to listen to
613
.Ar port
615
.Ar port
614
on the local side, and whenever a connection is made to this port, the
616
on the local side (optionally binding it to
617
.Ar listenhost
618
), and whenever a connection is made to this port, the
615
connection is forwarded over the secure channel, and a connection is
619
connection is forwarded over the secure channel, and a connection is
616
made to
620
made to
617
.Ar host
621
.Ar host
618
port
622
port
619
.Ar hostport
623
.Ar port
620
from the remote machine.
624
from the remote machine.
621
Port forwardings can also be specified in the configuration file.
625
Port forwardings can also be specified in the configuration file.
622
Only root can forward privileged ports.
626
Only root can forward privileged ports.
623
IPv6 addresses can be specified with an alternative syntax:
627
IPv6 addresses can be specified with an alternative syntax:
624
.Ar port/host/hostport
628
.Ar [listenhost/]listenport/host/port
625
.It Fl R Ar port:host:hostport
629
.It Fl R Ar [listenhost:]listenport:host:port
626
Specifies that the given port on the remote (server) host is to be
630
Specifies that the given port on the remote (server) host is to be
627
forwarded to the given host and port on the local side.
631
forwarded to the given host and port on the local side.
628
This works by allocating a socket to listen to
632
This works by allocating a socket to listen to
629
.Ar port
633
.Ar port
630
on the remote side, and whenever a connection is made to this port, the
634
on the remote side (optionally binding it to
635
.Ar listenhost
636
), and whenever a connection is made to this port, the
631
connection is forwarded over the secure channel, and a connection is
637
connection is forwarded over the secure channel, and a connection is
632
made to
638
made to
633
.Ar host
639
.Ar host
634
port
640
port
635
.Ar hostport
641
.Ar port
636
from the local machine.
642
from the local machine.
637
Port forwardings can also be specified in the configuration file.
643
Port forwardings can also be specified in the configuration file.
638
Privileged ports can be forwarded only when
644
Privileged ports can be forwarded only when
639
logging in as root on the remote machine.
645
logging in as root on the remote machine.
640
IPv6 addresses can be specified with an alternative syntax:
646
IPv6 addresses can be specified with an alternative syntax:
641
.Ar port/host/hostport
647
.Ar [listenhost/]listenport/host/port
642
.It Fl D Ar port
648
.It Fl D Ar [listenhost:]port
643
Specifies a local
649
Specifies a local
644
.Dq dynamic
650
.Dq dynamic
645
application-level port forwarding.
651
application-level port forwarding.
646
This works by allocating a socket to listen to
652
This works by allocating a socket to listen to
647
.Ar port
653
.Ar port
648
on the local side, and whenever a connection is made to this port, the
654
on the local side, (optionally binding it to
655
.Ar listenhost
656
) and whenever a connection is made to this port, the
649
connection is forwarded over the secure channel, and the application
657
connection is forwarded over the secure channel, and the application
650
protocol is then used to determine where to connect to from the
658
protocol is then used to determine where to connect to from the
651
remote machine.
659
remote machine.
(-)ssh.c (-40 / +69 lines)
Lines 180-190 Link Here
180
	fprintf(stderr, "  -c cipher   Select encryption algorithm\n");
180
	fprintf(stderr, "  -c cipher   Select encryption algorithm\n");
181
	fprintf(stderr, "  -m macs     Specify MAC algorithms for protocol version 2.\n");
181
	fprintf(stderr, "  -m macs     Specify MAC algorithms for protocol version 2.\n");
182
	fprintf(stderr, "  -p port     Connect to this port.  Server must be on the same port.\n");
182
	fprintf(stderr, "  -p port     Connect to this port.  Server must be on the same port.\n");
183
	fprintf(stderr, "  -L listen-port:host:port   Forward local port to remote address\n");
183
	fprintf(stderr, "  -L [listen-host]:listen-port:host:port   Forward local port to remote address\n");
184
	fprintf(stderr, "  -R listen-port:host:port   Forward remote port to local address\n");
184
	fprintf(stderr, "  -R [listen-host]:listen-port:host:port   Forward remote port to local address\n");
185
	fprintf(stderr, "              These cause %s to listen for connections on a port, and\n", __progname);
185
	fprintf(stderr, "              These cause %s to listen for connections on a port, and\n", __progname);
186
	fprintf(stderr, "              forward them to the other side by connecting to host:port.\n");
186
	fprintf(stderr, "              forward them to the other side by connecting to host:port.\n");
187
	fprintf(stderr, "  -D port     Enable dynamic application-level port forwarding.\n");
187
	fprintf(stderr, "  -D [listen-host]:port     Enable dynamic application-level port forwarding.\n");
188
	fprintf(stderr, "  -C          Enable compression.\n");
188
	fprintf(stderr, "  -C          Enable compression.\n");
189
	fprintf(stderr, "  -N          Do not execute a shell or command.\n");
189
	fprintf(stderr, "  -N          Do not execute a shell or command.\n");
190
	fprintf(stderr, "  -g          Allow remote hosts to connect to forwarded ports.\n");
190
	fprintf(stderr, "  -g          Allow remote hosts to connect to forwarded ports.\n");
Lines 209-222 Link Here
209
main(int ac, char **av)
209
main(int ac, char **av)
210
{
210
{
211
	int i, opt, exit_status;
211
	int i, opt, exit_status;
212
	u_short fwd_port, fwd_host_port;
212
	u_short fwd_lport;
213
	char sfwd_port[6], sfwd_host_port[6];
213
	char *fwd_lhost;
214
	char *p, *cp, buf[256];
214
	char *p, *cp, buf[256];
215
	struct stat st;
215
	struct stat st;
216
	struct passwd *pw;
216
	struct passwd *pw;
217
	int dummy;
217
	int dummy;
218
	extern int optind, optreset;
218
	extern int optind, optreset;
219
	extern char *optarg;
219
	extern char *optarg;
220
	Forward fwd;
220
221
221
	__progname = get_progname(av[0]);
222
	__progname = get_progname(av[0]);
222
	init_rng();
223
	init_rng();
Lines 422-460 Link Here
422
			break;
423
			break;
423
424
424
		case 'L':
425
		case 'L':
425
		case 'R':
426
			if (parse_forward(&fwd, optarg)) {
426
			if (sscanf(optarg, "%5[0123456789]:%255[^:]:%5[0123456789]",
427
				add_local_forward(&options,
427
			    sfwd_port, buf, sfwd_host_port) != 3 &&
428
				    fwd.listen_host, fwd.listen_port,
428
			    sscanf(optarg, "%5[0123456789]/%255[^/]/%5[0123456789]",
429
				    fwd.connect_host, fwd.connect_port);
429
			    sfwd_port, buf, sfwd_host_port) != 3) {
430
			} else {
430
				fprintf(stderr,
431
				fprintf(stderr,
431
				    "Bad forwarding specification '%s'\n",
432
				    "Bad forwarding specification '%s'\n",
432
				    optarg);
433
				    optarg);
433
				usage();
434
				usage();
435
				exit(1);
434
				/* NOTREACHED */
436
				/* NOTREACHED */
435
			}
437
			}
436
			if ((fwd_port = a2port(sfwd_port)) == 0 ||
438
			break;
437
			    (fwd_host_port = a2port(sfwd_host_port)) == 0) {
439
440
		case 'R':
441
			if (parse_forward(&fwd, optarg)) {
442
				add_remote_forward(&options,
443
				    fwd.listen_host, fwd.listen_port,
444
				    fwd.connect_host, fwd.connect_port);
445
			} else {
438
				fprintf(stderr,
446
				fprintf(stderr,
439
				    "Bad forwarding port(s) '%s'\n", optarg);
447
				    "Bad forwarding specification '%s'\n",
448
				    optarg);
449
				usage();
440
				exit(1);
450
				exit(1);
451
				/* NOTREACHED */
441
			}
452
			}
442
			if (opt == 'L')
443
				add_local_forward(&options, fwd_port, buf,
444
				    fwd_host_port);
445
			else if (opt == 'R')
446
				add_remote_forward(&options, fwd_port, buf,
447
				    fwd_host_port);
448
			break;
453
			break;
449
454
450
		case 'D':
455
		case 'D':
451
			fwd_port = a2port(optarg);
456
			cp = p = xstrdup(optarg);
452
			if (fwd_port == 0) {
457
			fwd_lport = 0;
458
			fwd_lhost = hpdelim(&cp);	/* may be NULL */
459
			if (cp) {
460
				fwd_lport = a2port(cp);
461
				fwd_lhost = cleanhostname(fwd_lhost);
462
			} else {
463
				fwd_lport = a2port(fwd_lhost);
464
				fwd_lhost = "";
465
			}
466
467
			if (fwd_lport == 0) {
453
				fprintf(stderr, "Bad dynamic port '%s'\n",
468
				fprintf(stderr, "Bad dynamic port '%s'\n",
454
				    optarg);
469
				    optarg);
470
				xfree(p);
455
				exit(1);
471
				exit(1);
456
			}
472
			}
457
			add_local_forward(&options, fwd_port, "socks4", 0);
473
			add_local_forward(&options,
474
			    fwd_lhost, fwd_lport, "socks4", 0);
475
			xfree(p);
458
			break;
476
			break;
459
477
460
		case 'C':
478
		case 'C':
Lines 805-821 Link Here
805
{
823
{
806
	int success = 0;
824
	int success = 0;
807
	int i;
825
	int i;
826
	char *listen_host;
808
827
809
	/* Initiate local TCP/IP port forwardings. */
828
	/* Initiate local TCP/IP port forwardings. */
810
	for (i = 0; i < options.num_local_forwards; i++) {
829
	for (i = 0; i < options.num_local_forwards; i++) {
811
		debug("Connections to local port %d forwarded to remote address %.200s:%d",
830
		listen_host = options.local_forwards[i].listen_host;
812
		    options.local_forwards[i].port,
831
		if (listen_host && listen_host[0] == '\0' && !options.gateway_ports)
813
		    options.local_forwards[i].host,
832
			listen_host = NULL;
814
		    options.local_forwards[i].host_port);
833
		debug("Local connections to %.200s:%d forwarded to remote address %.200s:%d",
834
		    listen_host,
835
		    options.local_forwards[i].listen_port,
836
		    options.local_forwards[i].connect_host,
837
		    options.local_forwards[i].connect_port);
815
		success += channel_setup_local_fwd_listener(
838
		success += channel_setup_local_fwd_listener(
816
		    options.local_forwards[i].port,
839
		    listen_host,
817
		    options.local_forwards[i].host,
840
		    options.local_forwards[i].listen_port,
818
		    options.local_forwards[i].host_port,
841
		    options.local_forwards[i].connect_host,
842
		    options.local_forwards[i].connect_port,
819
		    options.gateway_ports);
843
		    options.gateway_ports);
820
	}
844
	}
821
	if (i > 0 && success == 0)
845
	if (i > 0 && success == 0)
Lines 823-836 Link Here
823
847
824
	/* Initiate remote TCP/IP port forwardings. */
848
	/* Initiate remote TCP/IP port forwardings. */
825
	for (i = 0; i < options.num_remote_forwards; i++) {
849
	for (i = 0; i < options.num_remote_forwards; i++) {
826
		debug("Connections to remote port %d forwarded to local address %.200s:%d",
850
		listen_host = options.remote_forwards[i].listen_host;
827
		    options.remote_forwards[i].port,
851
		if (listen_host && listen_host[0] == '\0' && !options.gateway_ports)
828
		    options.remote_forwards[i].host,
852
			listen_host = NULL;
829
		    options.remote_forwards[i].host_port);
853
		debug("Remote connections from %.200s:%d forwarded to local address %.200s:%d",
854
		    listen_host,
855
		    options.remote_forwards[i].listen_port,
856
		    options.remote_forwards[i].connect_host,
857
		    options.remote_forwards[i].connect_port);
830
		channel_request_remote_forwarding(
858
		channel_request_remote_forwarding(
831
		    options.remote_forwards[i].port,
859
		    listen_host,
832
		    options.remote_forwards[i].host,
860
		    options.remote_forwards[i].listen_port,
833
		    options.remote_forwards[i].host_port);
861
		    options.remote_forwards[i].connect_host,
862
		    options.remote_forwards[i].connect_port);
834
	}
863
	}
835
}
864
}
836
865
Lines 1009-1020 Link Here
1009
	}
1038
	}
1010
	debug("remote forward %s for: listen %d, connect %s:%d",
1039
	debug("remote forward %s for: listen %d, connect %s:%d",
1011
	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1040
	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1012
	    options.remote_forwards[i].port,
1041
	    options.remote_forwards[i].listen_port,
1013
	    options.remote_forwards[i].host,
1042
	    options.remote_forwards[i].connect_host,
1014
	    options.remote_forwards[i].host_port);
1043
	    options.remote_forwards[i].connect_port);
1015
	if (type == SSH2_MSG_REQUEST_FAILURE)
1044
	if (type == SSH2_MSG_REQUEST_FAILURE)
1016
		logit("Warning: remote port forwarding failed for listen port %d",
1045
		logit("Warning: remote port forwarding failed for listen port %d",
1017
		    options.remote_forwards[i].port);
1046
		    options.remote_forwards[i].listen_port);
1018
}
1047
}
1019
1048
1020
/* request pty/x11/agent/tcpfwd/shell for channel */
1049
/* request pty/x11/agent/tcpfwd/shell for channel */

Return to bug 413