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

Collapse All | Expand All

(-)auth-options.c (-9 / +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-269 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);
261
				goto bad_option;
264
				goto bad_option;
262
			}
265
			}
263
			if (options.allow_tcp_forwarding)
264
				channel_add_permitted_opens(host, port);
265
			xfree(patterns);
266
			goto next_option;
267
		}
266
		}
268
next_option:
267
next_option:
269
		/*
268
		/*
(-)channels.c (-9 / +38 lines)
Lines 2020-2027 Link Here
2020
	Channel *c;
2020
	Channel *c;
2021
	int success, sock, on = 1;
2021
	int success, sock, on = 1;
2022
	struct addrinfo hints, *ai, *aitop;
2022
	struct addrinfo hints, *ai, *aitop;
2023
	const char *host;
2023
	const char *host, *addr;
2024
	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2024
	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2025
	int wildcard = 0, is_server = 0;
2025
2026
2026
	success = 0;
2027
	success = 0;
2027
	host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
2028
	host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
Lines 2035-2052 Link Here
2035
		error("Forward host name too long.");
2036
		error("Forward host name too long.");
2036
		return success;
2037
		return success;
2037
	}
2038
	}
2039
	/*
2040
	 * GatewayPorts is a default for the client, but a requirement
2041
	 * for the server.
2042
	 */
2043
	if (type == SSH_CHANNEL_RPORT_LISTENER || listen_addr == NULL)
2044
		is_server = 1;
2038
2045
2039
	/*
2046
	/*
2040
	 * getaddrinfo returns a loopback address if the hostname is
2047
	 * getaddrinfo returns a loopback address if the hostname is
2041
	 * set to NULL and hints.ai_flags is not AI_PASSIVE
2048
	 * set to NULL and hints.ai_flags is not AI_PASSIVE
2042
	 */
2049
	 */
2050
	if (is_server && !gateway_ports) {
2051
		/* enforce server policy */
2052
		addr = NULL;
2053
	} else {
2054
		if ( !listen_addr || listen_addr[0] == '\0' ||
2055
		     (!is_server && strcmp(listen_addr, "*") == 0) ) {
2056
			wildcard = 1;
2057
			addr = NULL;
2058
		} else {
2059
			if (listen_addr && listen_addr[0] == '\0')
2060
				addr = NULL;
2061
			else
2062
				addr = listen_addr;
2063
		}
2064
	}
2043
	memset(&hints, 0, sizeof(hints));
2065
	memset(&hints, 0, sizeof(hints));
2044
	hints.ai_family = IPv4or6;
2066
	hints.ai_family = IPv4or6;
2045
	hints.ai_flags = gateway_ports ? AI_PASSIVE : 0;
2067
	hints.ai_flags = wildcard ? AI_PASSIVE : 0;
2046
	hints.ai_socktype = SOCK_STREAM;
2068
	hints.ai_socktype = SOCK_STREAM;
2047
	snprintf(strport, sizeof strport, "%d", listen_port);
2069
	snprintf(strport, sizeof strport, "%d", listen_port);
2048
	if (getaddrinfo(NULL, strport, &hints, &aitop) != 0)
2070
	if (getaddrinfo(addr, strport, &hints, &aitop) != 0)
2049
		packet_disconnect("getaddrinfo: fatal error");
2071
		packet_disconnect("getaddrinfo: %.200s: fatal error",
2072
		    addr ? addr : "(NULL)");
2050
2073
2051
	for (ai = aitop; ai; ai = ai->ai_next) {
2074
	for (ai = aitop; ai; ai = ai->ai_next) {
2052
		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
2075
		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
Lines 2108-2118 Link Here
2108
2131
2109
/* protocol local port fwd, used by ssh (and sshd in v1) */
2132
/* protocol local port fwd, used by ssh (and sshd in v1) */
2110
int
2133
int
2111
channel_setup_local_fwd_listener(u_short listen_port,
2134
channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,
2112
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2135
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2113
{
2136
{
2114
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2137
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2115
	    NULL, listen_port, host_to_connect, port_to_connect, gateway_ports);
2138
	    listen_host, listen_port, host_to_connect, port_to_connect,
2139
	    gateway_ports);
2116
}
2140
}
2117
2141
2118
/* protocol v2 remote port fwd, used by sshd */
2142
/* protocol v2 remote port fwd, used by sshd */
Lines 2130-2136 Link Here
2130
 */
2154
 */
2131
2155
2132
void
2156
void
2133
channel_request_remote_forwarding(u_short listen_port,
2157
channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
2134
    const char *host_to_connect, u_short port_to_connect)
2158
    const char *host_to_connect, u_short port_to_connect)
2135
{
2159
{
2136
	int type, success = 0;
2160
	int type, success = 0;
Lines 2141-2147 Link Here
2141
2165
2142
	/* Send the forward request to the remote side. */
2166
	/* Send the forward request to the remote side. */
2143
	if (compat20) {
2167
	if (compat20) {
2144
		const char *address_to_bind = "0.0.0.0";
2168
		const char *address_to_bind;
2169
		if (listen_host[0] == '\0' || strcmp(listen_host, "*") == 0)
2170
			address_to_bind = "0.0.0.0";
2171
		else
2172
			address_to_bind = listen_host;
2173
2145
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
2174
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
2146
		packet_put_cstring("tcpip-forward");
2175
		packet_put_cstring("tcpip-forward");
2147
		packet_put_char(1);			/* boolean: want reply */
2176
		packet_put_char(1);			/* boolean: want reply */
Lines 2209-2215 Link Here
2209
				  port);
2238
				  port);
2210
#endif
2239
#endif
2211
	/* Initiate forwarding */
2240
	/* Initiate forwarding */
2212
	channel_setup_local_fwd_listener(port, hostname, host_port, gateway_ports);
2241
	channel_setup_local_fwd_listener(NULL, port, hostname, host_port, gateway_ports);
2213
2242
2214
	/* Free the argument string. */
2243
	/* Free the argument string. */
2215
	xfree(hostname);
2244
	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 / +9 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];
480
	/*char buf[1024], sfwd_port[6], sfwd_host_port[6]; */
481
	int local = 0;
481
	int local = 0;
482
482
483
	leave_raw_mode();
483
	leave_raw_mode();
Lines 499-529 Link Here
499
		log("Not supported for SSH protocol version 1.");
499
		log("Not supported for SSH protocol version 1.");
500
		goto out;
500
		goto out;
501
	}
501
	}
502
	s += 2;
503
	while (*s && isspace(*s))
504
		s++;
505
502
506
	if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]",
503
	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
		log("Bad forwarding specification.");
504
		log("Bad forwarding specification.");
511
		goto out;
505
		goto out;
512
	}
506
	}
513
	if ((fwd_port = a2port(sfwd_port)) == 0 ||
507
514
	    (fwd_host_port = a2port(sfwd_host_port)) == 0) {
515
		log("Bad forwarding port(s).");
516
		goto out;
517
	}
518
	if (local) {
508
	if (local) {
519
		if (channel_setup_local_fwd_listener(fwd_port, buf,
509
		if (channel_setup_local_fwd_listener(fwd.listen_host,
520
		    fwd_host_port, options.gateway_ports) < 0) {
510
		    fwd.listen_port, fwd.connect_host, fwd.connect_port,
511
		    options.gateway_ports) < 0) {
521
			log("Port forwarding failed.");
512
			log("Port forwarding failed.");
522
			goto out;
513
			goto out;
523
		}
514
		}
524
	} else
515
	} else
525
		channel_request_remote_forwarding(fwd_port, buf,
516
		channel_request_remote_forwarding(fwd.listen_host,
526
		    fwd_host_port);
517
		    fwd.listen_port, fwd.connect_host, fwd.connect_port);
527
	log("Forwarding port.");
518
	log("Forwarding port.");
528
out:
519
out:
529
	signal(SIGINT, handler);
520
	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 (-36 / +129 lines)
Lines 197-217 Link Here
197
 */
197
 */
198
198
199
void
199
void
200
add_local_forward(Options *options, u_short port, const char *host,
200
add_local_forward(Options *options, const char *listen_host,
201
		  u_short host_port)
201
		u_short listen_port, const char *connect_host,
202
		u_short connect_port)
202
{
203
{
203
	Forward *fwd;
204
	Forward *fwd;
204
#ifndef NO_IPPORT_RESERVED_CONCEPT
205
#ifndef NO_IPPORT_RESERVED_CONCEPT
205
	extern uid_t original_real_uid;
206
	extern uid_t original_real_uid;
206
	if (port < IPPORT_RESERVED && original_real_uid != 0)
207
	if (listen_port < IPPORT_RESERVED && original_real_uid != 0)
207
		fatal("Privileged ports can only be forwarded by root.");
208
		fatal("Privileged ports can only be forwarded by root.");
208
#endif
209
#endif
209
	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
210
	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
210
		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
211
		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
211
	fwd = &options->local_forwards[options->num_local_forwards++];
212
	fwd = &options->local_forwards[options->num_local_forwards++];
212
	fwd->port = port;
213
	fwd->listen_host = xstrdup(listen_host);
213
	fwd->host = xstrdup(host);
214
	fwd->listen_port = listen_port;
214
	fwd->host_port = host_port;
215
	fwd->connect_host = xstrdup(connect_host);
216
	fwd->connect_port = connect_port;
215
}
217
}
216
218
217
/*
219
/*
Lines 220-236 Link Here
220
 */
222
 */
221
223
222
void
224
void
223
add_remote_forward(Options *options, u_short port, const char *host,
225
add_remote_forward(Options *options, const char *listen_host,
224
		   u_short host_port)
226
		   u_short listen_port, const char *connect_host,
227
		   u_short connect_port)
225
{
228
{
226
	Forward *fwd;
229
	Forward *fwd;
227
	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
230
	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
228
		fatal("Too many remote forwards (max %d).",
231
		fatal("Too many remote forwards (max %d).",
229
		    SSH_MAX_FORWARDS_PER_DIRECTION);
232
		    SSH_MAX_FORWARDS_PER_DIRECTION);
230
	fwd = &options->remote_forwards[options->num_remote_forwards++];
233
	fwd = &options->remote_forwards[options->num_remote_forwards++];
231
	fwd->port = port;
234
	fwd->listen_host = xstrdup(listen_host);
232
	fwd->host = xstrdup(host);
235
	fwd->listen_port = listen_port;
233
	fwd->host_port = host_port;
236
	fwd->connect_host = xstrdup(connect_host);
237
	fwd->connect_port = connect_port;
234
}
238
}
235
239
236
static void
240
static void
Lines 238-248 Link Here
238
{
242
{
239
	int i;
243
	int i;
240
244
241
	for (i = 0; i < options->num_local_forwards; i++)
245
	for (i = 0; i < options->num_local_forwards; i++) {
242
		xfree(options->local_forwards[i].host);
246
		xfree(options->local_forwards[i].listen_host);
247
		xfree(options->local_forwards[i].connect_host);
248
	}
243
	options->num_local_forwards = 0;
249
	options->num_local_forwards = 0;
244
	for (i = 0; i < options->num_remote_forwards; i++)
250
	for (i = 0; i < options->num_remote_forwards; i++) {
245
		xfree(options->remote_forwards[i].host);
251
		xfree(options->remote_forwards[i].listen_host);
252
		xfree(options->remote_forwards[i].connect_host);
253
	}
246
	options->num_remote_forwards = 0;
254
	options->num_remote_forwards = 0;
247
}
255
}
248
256
Lines 274-283 Link Here
274
		    char *line, const char *filename, int linenum,
282
		    char *line, const char *filename, int linenum,
275
		    int *activep)
283
		    int *activep)
276
{
284
{
277
	char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg;
285
	char *s, *string, **charptr, *endofnumber, *keyword, *arg, *arg2;
278
	int opcode, *intptr, value;
286
	int opcode, *intptr, value, i;
279
	u_short fwd_port, fwd_host_port;
287
	u_short fwd_lport, fwd_cport;
280
	char sfwd_host_port[6];
288
	char *fwd_lhost, *fwd_chost, *fwdarg[4];
281
289
282
	s = line;
290
	s = line;
283
	/* Get the keyword. (Each line is supposed to begin with a keyword). */
291
	/* Get the keyword. (Each line is supposed to begin with a keyword). */
Lines 597-623 Link Here
597
		if (!arg || *arg == '\0')
605
		if (!arg || *arg == '\0')
598
			fatal("%.200s line %d: Missing port argument.",
606
			fatal("%.200s line %d: Missing port argument.",
599
			    filename, linenum);
607
			    filename, linenum);
600
		if ((fwd_port = a2port(arg)) == 0)
608
		arg2 = strdelim(&s); /* optional second arg */
601
			fatal("%.200s line %d: Bad listen port.",
609
602
			    filename, linenum);
610
		for (i = 0; i < 4; ++i) {
603
		arg = strdelim(&s);
611
			fwdarg[i] = hpdelim(&arg);
604
		if (!arg || *arg == '\0')
612
			if (!fwdarg[i])
605
			fatal("%.200s line %d: Missing second argument.",
613
				break;
606
			    filename, linenum);
614
			if (i<2 && !arg && arg2) {
607
		if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 &&
615
				arg = arg2;
608
		    sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
616
				arg2 = NULL;
617
			}
618
		}
619
		switch(i) {
620
		case 3:
621
			fwd_lhost = "";
622
			fwd_lport = a2port(fwdarg[0]);
623
			fwd_chost = cleanhostname(fwdarg[1]);
624
			fwd_cport = a2port(fwdarg[2]);
625
			break;
626
		case 4:
627
			fwd_lhost = cleanhostname(fwdarg[0]);
628
			fwd_lport = a2port(fwdarg[1]);
629
			fwd_chost = cleanhostname(fwdarg[2]);
630
			fwd_cport = a2port(fwdarg[3]);
631
			
632
			break;
633
		default:
609
			fatal("%.200s line %d: Bad forwarding specification.",
634
			fatal("%.200s line %d: Bad forwarding specification.",
610
			    filename, linenum);
635
			    filename, linenum);
611
		if ((fwd_host_port = a2port(sfwd_host_port)) == 0)
636
			/* NOTREACHED */
637
		}
638
639
		if (fwd_lport == 0)
640
			fatal("%.200s line %d: Bad listen port.",
641
			    filename, linenum);
642
		if (fwd_cport == 0)
612
			fatal("%.200s line %d: Bad forwarding port.",
643
			fatal("%.200s line %d: Bad forwarding port.",
613
			    filename, linenum);
644
			    filename, linenum);
645
614
		if (*activep) {
646
		if (*activep) {
615
			if (opcode == oLocalForward)
647
			if (opcode == oLocalForward)
616
				add_local_forward(options, fwd_port, buf,
648
				add_local_forward(options,
617
				    fwd_host_port);
649
				    fwd_lhost, fwd_lport,
650
				    fwd_chost, fwd_cport);
618
			else if (opcode == oRemoteForward)
651
			else if (opcode == oRemoteForward)
619
				add_remote_forward(options, fwd_port, buf,
652
				add_remote_forward(options,
620
				    fwd_host_port);
653
				    fwd_lhost, fwd_lport,
654
				    fwd_chost, fwd_cport);
621
		}
655
		}
622
		break;
656
		break;
623
657
Lines 626-637 Link Here
626
		if (!arg || *arg == '\0')
660
		if (!arg || *arg == '\0')
627
			fatal("%.200s line %d: Missing port argument.",
661
			fatal("%.200s line %d: Missing port argument.",
628
			    filename, linenum);
662
			    filename, linenum);
629
		fwd_port = a2port(arg);
663
		fwd_lport = 0;
630
		if (fwd_port == 0)
664
		fwd_lhost = hpdelim(&arg);
665
		if (!fwd_lhost)
666
			fatal("%.200s line %d: Bad forwarding specification.",
667
			    filename, linenum);
668
		if (arg) {
669
			fwd_lport = a2port(arg);
670
			fwd_lhost = cleanhostname(fwd_lhost);
671
		} else {
672
			fwd_lport = a2port(fwd_lhost);
673
			fwd_lhost = "";
674
		}
675
		if (fwd_lport == 0)
631
			fatal("%.200s line %d: Badly formatted port number.",
676
			fatal("%.200s line %d: Badly formatted port number.",
632
			    filename, linenum);
677
			    filename, linenum);
633
		if (*activep)
678
		if (*activep)
634
			add_local_forward(options, fwd_port, "socks4", 0);
679
			add_local_forward(options, fwd_lhost, fwd_lport,
680
			    "socks4", 0);
635
		break;
681
		break;
636
682
637
	case oClearAllForwardings:
683
	case oClearAllForwardings:
Lines 921-924 Link Here
921
	/* options->hostname will be set in the main program if appropriate */
967
	/* options->hostname will be set in the main program if appropriate */
922
	/* options->host_key_alias should not be set by default */
968
	/* options->host_key_alias should not be set by default */
923
	/* options->preferred_authentications will be set in ssh */
969
	/* options->preferred_authentications will be set in ssh */
970
}
971
972
/*
973
 * parse_forward
974
 * parses a string containing a port forwarding specification of the form:
975
 *	[listenhost:]listenport:connecthost:connectport
976
 * returns number of arguments parsed or zero on error
977
 */
978
int
979
parse_forward(Forward *fwd, const char *fwdspec)
980
{
981
	int i;
982
	char *p, *cp, *fwdarg[4];
983
984
	cp = p = xstrdup(fwdspec);
985
986
	/* skip leading spaces */
987
	while (*cp && isspace(*cp))
988
		cp++;
989
990
	for (i = 0; i < 4; ++i)
991
		if ( !(fwdarg[i] = hpdelim(&cp)) )
992
			break;
993
	switch(i) {
994
	case 3:
995
		fwd->listen_host = xstrdup("");
996
		fwd->listen_port = a2port(fwdarg[0]);
997
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
998
		fwd->connect_port = a2port(fwdarg[2]);
999
		break;
1000
1001
	case 4:
1002
		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1003
		fwd->listen_port = a2port(fwdarg[1]);
1004
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1005
		fwd->connect_port = a2port(fwdarg[3]);
1006
		break;
1007
	default:
1008
		i = 0; /* failure */
1009
	}
1010
1011
	xfree(p);
1012
1013
	if (fwd->listen_port == 0 && fwd->connect_port == 0)
1014
		i = 0;	/* failure */
1015
1016
	return(i);
924
}
1017
}
(-)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 108-118 Link Here
108
void     initialize_options(Options *);
109
void     initialize_options(Options *);
109
void     fill_default_options(Options *);
110
void     fill_default_options(Options *);
110
int	 read_config_file(const char *, const char *, Options *);
111
int	 read_config_file(const char *, const char *, Options *);
112
int	 parse_forward(Forward *, const char *);
111
113
112
int
114
int
113
process_config_line(Options *, const char *, char *, const char *, int, int *);
115
process_config_line(Options *, const char *, char *, const char *, int, int *);
114
116
115
void	 add_local_forward(Options *, u_short, const char *, u_short);
117
void
116
void	 add_remote_forward(Options *, u_short, const char *, u_short);
118
add_local_forward(Options *, const char *, u_short, const char *, u_short);
119
void
120
add_remote_forward(Options *, const char *, u_short, const char *, u_short);
117
121
118
#endif				/* READCONF_H */
122
#endif				/* READCONF_H */
(-)servconf.c (-28 / +17 lines)
Lines 445-450 Link Here
445
	char *cp, **charptr, *arg, *p;
445
	char *cp, **charptr, *arg, *p;
446
	int *intptr, value, i, n;
446
	int *intptr, value, i, n;
447
	ServerOpCodes opcode;
447
	ServerOpCodes opcode;
448
	ushort port;
448
449
449
	cp = line;
450
	cp = line;
450
	arg = strdelim(&cp);
451
	arg = strdelim(&cp);
Lines 517-555 Link Here
517
518
518
	case sListenAddress:
519
	case sListenAddress:
519
		arg = strdelim(&cp);
520
		arg = strdelim(&cp);
520
		if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
521
		if (!arg || *arg == '\0')
521
			fatal("%s line %d: missing inet addr.",
522
			fatal("%s line %d: missing inet addr.",
522
			    filename, linenum);
523
			    filename, linenum);
523
		if (*arg == '[') {
524
		p = hpdelim(&arg);
524
			if ((p = strchr(arg, ']')) == NULL)
525
		if (!p)
525
				fatal("%s line %d: bad ipv6 inet addr usage.",
526
			fatal("%s line %d: bad inet addr:port usage.",
527
			    filename, linenum);
528
		p = cleanhostname(p);
529
		if (arg) {
530
			port = a2port(arg);
531
			if (port == 0) {
532
				fatal("%s line %d: bad port number.",
526
				    filename, linenum);
533
				    filename, linenum);
527
			arg++;
534
				/* NOTREACHED */
528
			memmove(p, p+1, strlen(p+1)+1);
535
			}
529
		} else if (((p = strchr(arg, ':')) == NULL) ||
536
		} else {
530
			    (strchr(p+1, ':') != NULL)) {
537
			port = 0;
531
			add_listen_addr(options, arg, 0);
532
			break;
533
		}
538
		}
534
		if (*p == ':') {
535
			u_short port;
536
539
537
			p++;
540
		add_listen_addr(options, p, port);
538
			if (*p == '\0')
541
539
				fatal("%s line %d: bad inet addr:port usage.",
540
				    filename, linenum);
541
			else {
542
				*(p-1) = '\0';
543
				if ((port = a2port(p)) == 0)
544
					fatal("%s line %d: bad port number.",
545
					    filename, linenum);
546
				add_listen_addr(options, arg, port);
547
			}
548
		} else if (*p == '\0')
549
			add_listen_addr(options, arg, 0);
550
		else
551
			fatal("%s line %d: bad inet addr usage.",
552
			    filename, linenum);
553
		break;
542
		break;
554
543
555
	case sHostKeyFile:
544
	case sHostKeyFile:
(-)ssh.1 (-14 / +22 lines)
Lines 60-76 Link Here
60
.Op Fl F Ar configfile
60
.Op Fl F Ar configfile
61
.Oo Fl L Xo
61
.Oo Fl L Xo
62
.Sm off
62
.Sm off
63
.Ar port :
63
.Ar [ listenhost : ]
64
.Ar listenport :
64
.Ar host :
65
.Ar host :
65
.Ar hostport
66
.Ar port
66
.Sm on
67
.Sm on
67
.Xc
68
.Xc
68
.Oc
69
.Oc
69
.Oo Fl R Xo
70
.Oo Fl R Xo
70
.Sm off
71
.Sm off
71
.Ar port :
72
.Ar [ listenhost : ]
73
.Ar listenport :
72
.Ar host :
74
.Ar host :
73
.Ar hostport
75
.Ar port
74
.Sm on
76
.Sm on
75
.Xc
77
.Xc
76
.Oc
78
.Oc
Lines 595-640 Link Here
595
will be ignored.
597
will be ignored.
596
The default for the per-user configuration file is
598
The default for the per-user configuration file is
597
.Pa $HOME/.ssh/config .
599
.Pa $HOME/.ssh/config .
598
.It Fl L Ar port:host:hostport
600
.It Fl L Ar [listenhost:]listenport:host:port
599
Specifies that the given port on the local (client) host is to be
601
Specifies that the given port on the local (client) host is to be
600
forwarded to the given host and port on the remote side.
602
forwarded to the given host and port on the remote side.
601
This works by allocating a socket to listen to
603
This works by allocating a socket to listen to
602
.Ar port
604
.Ar port
603
on the local side, and whenever a connection is made to this port, the
605
on the local side (optionally binding it to
606
.Ar listenhost
607
), and whenever a connection is made to this port, the
604
connection is forwarded over the secure channel, and a connection is
608
connection is forwarded over the secure channel, and a connection is
605
made to
609
made to
606
.Ar host
610
.Ar host
607
port
611
port
608
.Ar hostport
612
.Ar port
609
from the remote machine.
613
from the remote machine.
610
Port forwardings can also be specified in the configuration file.
614
Port forwardings can also be specified in the configuration file.
611
Only root can forward privileged ports.
615
Only root can forward privileged ports.
612
IPv6 addresses can be specified with an alternative syntax:
616
IPv6 addresses can be specified with an alternative syntax:
613
.Ar port/host/hostport
617
.Ar [listenhost/]listenport/host/port
614
.It Fl R Ar port:host:hostport
618
.It Fl R Ar [listenhost:]listenport:host:port
615
Specifies that the given port on the remote (server) host is to be
619
Specifies that the given port on the remote (server) host is to be
616
forwarded to the given host and port on the local side.
620
forwarded to the given host and port on the local side.
617
This works by allocating a socket to listen to
621
This works by allocating a socket to listen to
618
.Ar port
622
.Ar port
619
on the remote side, and whenever a connection is made to this port, the
623
on the remote side (optionally binding it to
624
.Ar listenhost
625
), and whenever a connection is made to this port, the
620
connection is forwarded over the secure channel, and a connection is
626
connection is forwarded over the secure channel, and a connection is
621
made to
627
made to
622
.Ar host
628
.Ar host
623
port
629
port
624
.Ar hostport
630
.Ar port
625
from the local machine.
631
from the local machine.
626
Port forwardings can also be specified in the configuration file.
632
Port forwardings can also be specified in the configuration file.
627
Privileged ports can be forwarded only when
633
Privileged ports can be forwarded only when
628
logging in as root on the remote machine.
634
logging in as root on the remote machine.
629
IPv6 addresses can be specified with an alternative syntax:
635
IPv6 addresses can be specified with an alternative syntax:
630
.Ar port/host/hostport
636
.Ar [listenhost/]listenport/host/port
631
.It Fl D Ar port
637
.It Fl D Ar [listenhost:]port
632
Specifies a local
638
Specifies a local
633
.Dq dynamic
639
.Dq dynamic
634
application-level port forwarding.
640
application-level port forwarding.
635
This works by allocating a socket to listen to
641
This works by allocating a socket to listen to
636
.Ar port
642
.Ar port
637
on the local side, and whenever a connection is made to this port, the
643
on the local side, (optionally binding it to
644
.Ar listenhost
645
) and whenever a connection is made to this port, the
638
connection is forwarded over the secure channel, and the application
646
connection is forwarded over the secure channel, and the application
639
protocol is then used to determine where to connect to from the
647
protocol is then used to determine where to connect to from the
640
remote machine.  Currently the SOCKS4 protocol is supported, and
648
remote machine.  Currently the SOCKS4 protocol is supported, and
(-)ssh.c (-40 / +69 lines)
Lines 184-194 Link Here
184
	fprintf(stderr, "  -c cipher   Select encryption algorithm\n");
184
	fprintf(stderr, "  -c cipher   Select encryption algorithm\n");
185
	fprintf(stderr, "  -m macs     Specify MAC algorithms for protocol version 2.\n");
185
	fprintf(stderr, "  -m macs     Specify MAC algorithms for protocol version 2.\n");
186
	fprintf(stderr, "  -p port     Connect to this port.  Server must be on the same port.\n");
186
	fprintf(stderr, "  -p port     Connect to this port.  Server must be on the same port.\n");
187
	fprintf(stderr, "  -L listen-port:host:port   Forward local port to remote address\n");
187
	fprintf(stderr, "  -L [listen-host]:listen-port:host:port   Forward local port to remote address\n");
188
	fprintf(stderr, "  -R listen-port:host:port   Forward remote port to local address\n");
188
	fprintf(stderr, "  -R [listen-host]:listen-port:host:port   Forward remote port to local address\n");
189
	fprintf(stderr, "              These cause %s to listen for connections on a port, and\n", __progname);
189
	fprintf(stderr, "              These cause %s to listen for connections on a port, and\n", __progname);
190
	fprintf(stderr, "              forward them to the other side by connecting to host:port.\n");
190
	fprintf(stderr, "              forward them to the other side by connecting to host:port.\n");
191
	fprintf(stderr, "  -D port     Enable dynamic application-level port forwarding.\n");
191
	fprintf(stderr, "  -D [listen-host]:port     Enable dynamic application-level port forwarding.\n");
192
	fprintf(stderr, "  -C          Enable compression.\n");
192
	fprintf(stderr, "  -C          Enable compression.\n");
193
	fprintf(stderr, "  -N          Do not execute a shell or command.\n");
193
	fprintf(stderr, "  -N          Do not execute a shell or command.\n");
194
	fprintf(stderr, "  -g          Allow remote hosts to connect to forwarded ports.\n");
194
	fprintf(stderr, "  -g          Allow remote hosts to connect to forwarded ports.\n");
Lines 213-226 Link Here
213
main(int ac, char **av)
213
main(int ac, char **av)
214
{
214
{
215
	int i, opt, exit_status;
215
	int i, opt, exit_status;
216
	u_short fwd_port, fwd_host_port;
216
	u_short fwd_lport;
217
	char sfwd_port[6], sfwd_host_port[6];
217
	char *fwd_lhost;
218
	char *p, *cp, buf[256];
218
	char *p, *cp, buf[256];
219
	struct stat st;
219
	struct stat st;
220
	struct passwd *pw;
220
	struct passwd *pw;
221
	int dummy;
221
	int dummy;
222
	extern int optind, optreset;
222
	extern int optind, optreset;
223
	extern char *optarg;
223
	extern char *optarg;
224
	Forward fwd;
224
225
225
	__progname = get_progname(av[0]);
226
	__progname = get_progname(av[0]);
226
	init_rng();
227
	init_rng();
Lines 426-464 Link Here
426
			break;
427
			break;
427
428
428
		case 'L':
429
		case 'L':
429
		case 'R':
430
			if (parse_forward(&fwd, optarg)) {
430
			if (sscanf(optarg, "%5[0-9]:%255[^:]:%5[0-9]",
431
				add_local_forward(&options,
431
			    sfwd_port, buf, sfwd_host_port) != 3 &&
432
				    fwd.listen_host, fwd.listen_port,
432
			    sscanf(optarg, "%5[0-9]/%255[^/]/%5[0-9]",
433
				    fwd.connect_host, fwd.connect_port);
433
			    sfwd_port, buf, sfwd_host_port) != 3) {
434
			} else {
434
				fprintf(stderr,
435
				fprintf(stderr,
435
				    "Bad forwarding specification '%s'\n",
436
				    "Bad forwarding specification '%s'\n",
436
				    optarg);
437
				    optarg);
437
				usage();
438
				usage();
439
				exit(1);
438
				/* NOTREACHED */
440
				/* NOTREACHED */
439
			}
441
			}
440
			if ((fwd_port = a2port(sfwd_port)) == 0 ||
442
			break;
441
			    (fwd_host_port = a2port(sfwd_host_port)) == 0) {
443
444
		case 'R':
445
			if (parse_forward(&fwd, optarg)) {
446
				add_remote_forward(&options,
447
				    fwd.listen_host, fwd.listen_port,
448
				    fwd.connect_host, fwd.connect_port);
449
			} else {
442
				fprintf(stderr,
450
				fprintf(stderr,
443
				    "Bad forwarding port(s) '%s'\n", optarg);
451
				    "Bad forwarding specification '%s'\n",
452
				    optarg);
453
				usage();
444
				exit(1);
454
				exit(1);
455
				/* NOTREACHED */
445
			}
456
			}
446
			if (opt == 'L')
447
				add_local_forward(&options, fwd_port, buf,
448
				    fwd_host_port);
449
			else if (opt == 'R')
450
				add_remote_forward(&options, fwd_port, buf,
451
				    fwd_host_port);
452
			break;
457
			break;
453
458
454
		case 'D':
459
		case 'D':
455
			fwd_port = a2port(optarg);
460
			cp = p = xstrdup(optarg);
456
			if (fwd_port == 0) {
461
			fwd_lport = 0;
462
			fwd_lhost = hpdelim(&cp);	/* may be NULL */
463
			if (cp) {
464
				fwd_lport = a2port(cp);
465
				fwd_lhost = cleanhostname(fwd_lhost);
466
			} else {
467
				fwd_lport = a2port(fwd_lhost);
468
				fwd_lhost = "";
469
			}
470
471
			if (fwd_lport == 0) {
457
				fprintf(stderr, "Bad dynamic port '%s'\n",
472
				fprintf(stderr, "Bad dynamic port '%s'\n",
458
				    optarg);
473
				    optarg);
474
				xfree(p);
459
				exit(1);
475
				exit(1);
460
			}
476
			}
461
			add_local_forward(&options, fwd_port, "socks4", 0);
477
			add_local_forward(&options,
478
			    fwd_lhost, fwd_lport, "socks4", 0);
479
			xfree(p);
462
			break;
480
			break;
463
481
464
		case 'C':
482
		case 'C':
Lines 806-822 Link Here
806
{
824
{
807
	int success = 0;
825
	int success = 0;
808
	int i;
826
	int i;
827
	char *listen_host;
809
828
810
	/* Initiate local TCP/IP port forwardings. */
829
	/* Initiate local TCP/IP port forwardings. */
811
	for (i = 0; i < options.num_local_forwards; i++) {
830
	for (i = 0; i < options.num_local_forwards; i++) {
812
		debug("Connections to local port %d forwarded to remote address %.200s:%d",
831
		listen_host = options.local_forwards[i].listen_host;
813
		    options.local_forwards[i].port,
832
		if (listen_host[0] == '\0' && !options.gateway_ports)
814
		    options.local_forwards[i].host,
833
			listen_host = "localhost";
815
		    options.local_forwards[i].host_port);
834
		debug("Connections to local port %.200s:%d forwarded to remote address %.200s:%d",
835
		    listen_host,
836
		    options.local_forwards[i].listen_port,
837
		    options.local_forwards[i].connect_host,
838
		    options.local_forwards[i].connect_port);
816
		success += channel_setup_local_fwd_listener(
839
		success += channel_setup_local_fwd_listener(
817
		    options.local_forwards[i].port,
840
		    listen_host,
818
		    options.local_forwards[i].host,
841
		    options.local_forwards[i].listen_port,
819
		    options.local_forwards[i].host_port,
842
		    options.local_forwards[i].connect_host,
843
		    options.local_forwards[i].connect_port,
820
		    options.gateway_ports);
844
		    options.gateway_ports);
821
	}
845
	}
822
	if (i > 0 && success == 0)
846
	if (i > 0 && success == 0)
Lines 824-837 Link Here
824
848
825
	/* Initiate remote TCP/IP port forwardings. */
849
	/* Initiate remote TCP/IP port forwardings. */
826
	for (i = 0; i < options.num_remote_forwards; i++) {
850
	for (i = 0; i < options.num_remote_forwards; i++) {
827
		debug("Connections to remote port %d forwarded to local address %.200s:%d",
851
		listen_host = options.remote_forwards[i].listen_host;
828
		    options.remote_forwards[i].port,
852
		if (listen_host[0] == '\0' && !options.gateway_ports)
829
		    options.remote_forwards[i].host,
853
			listen_host = "localhost";
830
		    options.remote_forwards[i].host_port);
854
		debug("Connections to remote port %.200s:%d forwarded to local address %.200s:%d",
855
		    listen_host,
856
		    options.remote_forwards[i].listen_port,
857
		    options.remote_forwards[i].connect_host,
858
		    options.remote_forwards[i].connect_port);
831
		channel_request_remote_forwarding(
859
		channel_request_remote_forwarding(
832
		    options.remote_forwards[i].port,
860
		    listen_host,
833
		    options.remote_forwards[i].host,
861
		    options.remote_forwards[i].listen_port,
834
		    options.remote_forwards[i].host_port);
862
		    options.remote_forwards[i].connect_host,
863
		    options.remote_forwards[i].connect_port);
835
	}
864
	}
836
}
865
}
837
866
Lines 1010-1021 Link Here
1010
	}
1039
	}
1011
	debug("remote forward %s for: listen %d, connect %s:%d",
1040
	debug("remote forward %s for: listen %d, connect %s:%d",
1012
	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1041
	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1013
	    options.remote_forwards[i].port,
1042
	    options.remote_forwards[i].listen_port,
1014
	    options.remote_forwards[i].host,
1043
	    options.remote_forwards[i].connect_host,
1015
	    options.remote_forwards[i].host_port);
1044
	    options.remote_forwards[i].connect_port);
1016
	if (type == SSH2_MSG_REQUEST_FAILURE)
1045
	if (type == SSH2_MSG_REQUEST_FAILURE)
1017
		log("Warning: remote port forwarding failed for listen port %d",
1046
		log("Warning: remote port forwarding failed for listen port %d",
1018
		    options.remote_forwards[i].port);
1047
		    options.remote_forwards[i].listen_port);
1019
}
1048
}
1020
1049
1021
/* request pty/x11/agent/tcpfwd/shell for channel */
1050
/* request pty/x11/agent/tcpfwd/shell for channel */

Return to bug 413