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 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 = NULL;
2024
	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2024
	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2025
	int wildcard = 0;
2025
2026
2026
	success = 0;
2027
	success = 0;
2027
	host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
2028
	host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
Lines 2037-2052 Link Here
2037
	}
2038
	}
2038
2039
2039
	/*
2040
	/*
2041
	 * Determine whether or not a port forward listens to loopback,
2042
	 * specified address or wildcard.
2043
	 */
2044
	if (gateway_ports) {
2045
		if (listen_addr == NULL || listen_addr[0] == '\0' ||
2046
		    strcmp(listen_addr, "*") == 0)
2047
				wildcard = 1;
2048
			else
2049
				addr = listen_addr;
2050
	} else if (type == SSH_CHANNEL_PORT_LISTENER) {
2051
		/* A client may override GatewayPorts with a wildcard */
2052
		if (listen_addr != NULL && strcmp(listen_addr, "*") == 0)
2053
			wildcard = 1;
2054
		else
2055
			addr = listen_addr;
2056
	}
2057
2058
	/*
2040
	 * getaddrinfo returns a loopback address if the hostname is
2059
	 * getaddrinfo returns a loopback address if the hostname is
2041
	 * set to NULL and hints.ai_flags is not AI_PASSIVE
2060
	 * set to NULL and hints.ai_flags is not AI_PASSIVE
2042
	 */
2061
	 */
2043
	memset(&hints, 0, sizeof(hints));
2062
	memset(&hints, 0, sizeof(hints));
2044
	hints.ai_family = IPv4or6;
2063
	hints.ai_family = IPv4or6;
2045
	hints.ai_flags = gateway_ports ? AI_PASSIVE : 0;
2064
	hints.ai_flags = wildcard ? AI_PASSIVE : 0;
2046
	hints.ai_socktype = SOCK_STREAM;
2065
	hints.ai_socktype = SOCK_STREAM;
2047
	snprintf(strport, sizeof strport, "%d", listen_port);
2066
	snprintf(strport, sizeof strport, "%d", listen_port);
2048
	if (getaddrinfo(NULL, strport, &hints, &aitop) != 0)
2067
	if (getaddrinfo(addr, strport, &hints, &aitop) != 0)
2049
		packet_disconnect("getaddrinfo: fatal error");
2068
		packet_disconnect("getaddrinfo: %.200s: fatal error",
2069
		    addr ? addr : "(NULL)");
2050
2070
2051
	for (ai = aitop; ai; ai = ai->ai_next) {
2071
	for (ai = aitop; ai; ai = ai->ai_next) {
2052
		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
2072
		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
Lines 2108-2118 Link Here
2108
2128
2109
/* protocol local port fwd, used by ssh (and sshd in v1) */
2129
/* protocol local port fwd, used by ssh (and sshd in v1) */
2110
int
2130
int
2111
channel_setup_local_fwd_listener(u_short listen_port,
2131
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)
2132
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2113
{
2133
{
2114
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2134
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2115
	    NULL, listen_port, host_to_connect, port_to_connect, gateway_ports);
2135
	    listen_host, listen_port, host_to_connect, port_to_connect,
2136
	    gateway_ports);
2116
}
2137
}
2117
2138
2118
/* protocol v2 remote port fwd, used by sshd */
2139
/* protocol v2 remote port fwd, used by sshd */
Lines 2130-2136 Link Here
2130
 */
2151
 */
2131
2152
2132
void
2153
void
2133
channel_request_remote_forwarding(u_short listen_port,
2154
channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
2134
    const char *host_to_connect, u_short port_to_connect)
2155
    const char *host_to_connect, u_short port_to_connect)
2135
{
2156
{
2136
	int type, success = 0;
2157
	int type, success = 0;
Lines 2141-2147 Link Here
2141
2162
2142
	/* Send the forward request to the remote side. */
2163
	/* Send the forward request to the remote side. */
2143
	if (compat20) {
2164
	if (compat20) {
2144
		const char *address_to_bind = "0.0.0.0";
2165
		const char *address_to_bind;
2166
		if (listen_host == NULL)
2167
			address_to_bind = "127.0.0.1";
2168
		else if (listen_host[0] == '\0' || strcmp(listen_host, "*")==0)
2169
			address_to_bind = "0.0.0.0";
2170
		else
2171
			address_to_bind = listen_host;
2172
2145
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
2173
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
2146
		packet_put_cstring("tcpip-forward");
2174
		packet_put_cstring("tcpip-forward");
2147
		packet_put_char(1);			/* boolean: want reply */
2175
		packet_put_char(1);			/* boolean: want reply */
Lines 2209-2215 Link Here
2209
				  port);
2237
				  port);
2210
#endif
2238
#endif
2211
	/* Initiate forwarding */
2239
	/* Initiate forwarding */
2212
	channel_setup_local_fwd_listener(port, hostname, host_port, gateway_ports);
2240
	channel_setup_local_fwd_listener(NULL, port, hostname, host_port, gateway_ports);
2213
2241
2214
	/* Free the argument string. */
2242
	/* Free the argument string. */
2215
	xfree(hostname);
2243
	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 (-33 / +112 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
	if (listen_host == NULL)
213
	fwd->host = xstrdup(host);
214
		fwd->listen_host = NULL;
214
	fwd->host_port = host_port;
215
	else
216
		fwd->listen_host = xstrdup(listen_host);
217
	fwd->listen_port = listen_port;
218
	fwd->connect_host = xstrdup(connect_host);
219
	fwd->connect_port = connect_port;
215
}
220
}
216
221
217
/*
222
/*
Lines 220-236 Link Here
220
 */
225
 */
221
226
222
void
227
void
223
add_remote_forward(Options *options, u_short port, const char *host,
228
add_remote_forward(Options *options, const char *listen_host,
224
		   u_short host_port)
229
		   u_short listen_port, const char *connect_host,
230
		   u_short connect_port)
225
{
231
{
226
	Forward *fwd;
232
	Forward *fwd;
227
	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
233
	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
228
		fatal("Too many remote forwards (max %d).",
234
		fatal("Too many remote forwards (max %d).",
229
		    SSH_MAX_FORWARDS_PER_DIRECTION);
235
		    SSH_MAX_FORWARDS_PER_DIRECTION);
230
	fwd = &options->remote_forwards[options->num_remote_forwards++];
236
	fwd = &options->remote_forwards[options->num_remote_forwards++];
231
	fwd->port = port;
237
	if (listen_host == NULL)
232
	fwd->host = xstrdup(host);
238
		fwd->listen_host = NULL;
233
	fwd->host_port = host_port;
239
	else
240
		fwd->listen_host = xstrdup(listen_host);
241
	fwd->listen_port = listen_port;
242
	fwd->connect_host = xstrdup(connect_host);
243
	fwd->connect_port = connect_port;
234
}
244
}
235
245
236
static void
246
static void
Lines 238-248 Link Here
238
{
248
{
239
	int i;
249
	int i;
240
250
241
	for (i = 0; i < options->num_local_forwards; i++)
251
	for (i = 0; i < options->num_local_forwards; i++) {
242
		xfree(options->local_forwards[i].host);
252
		xfree(options->local_forwards[i].listen_host);
253
		xfree(options->local_forwards[i].connect_host);
254
	}
243
	options->num_local_forwards = 0;
255
	options->num_local_forwards = 0;
244
	for (i = 0; i < options->num_remote_forwards; i++)
256
	for (i = 0; i < options->num_remote_forwards; i++) {
245
		xfree(options->remote_forwards[i].host);
257
		xfree(options->remote_forwards[i].listen_host);
258
		xfree(options->remote_forwards[i].connect_host);
259
	}
246
	options->num_remote_forwards = 0;
260
	options->num_remote_forwards = 0;
247
}
261
}
248
262
Lines 274-283 Link Here
274
		    char *line, const char *filename, int linenum,
288
		    char *line, const char *filename, int linenum,
275
		    int *activep)
289
		    int *activep)
276
{
290
{
277
	char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg;
291
	char *s, *string, **charptr, *endofnumber, *keyword, *arg, *arg2,
292
	    fwdarg[256];
278
	int opcode, *intptr, value;
293
	int opcode, *intptr, value;
279
	u_short fwd_port, fwd_host_port;
294
	Forward fwd;
280
	char sfwd_host_port[6];
281
295
282
	s = line;
296
	s = line;
283
	/* Get the keyword. (Each line is supposed to begin with a keyword). */
297
	/* Get the keyword. (Each line is supposed to begin with a keyword). */
Lines 597-623 Link Here
597
		if (!arg || *arg == '\0')
611
		if (!arg || *arg == '\0')
598
			fatal("%.200s line %d: Missing port argument.",
612
			fatal("%.200s line %d: Missing port argument.",
599
			    filename, linenum);
613
			    filename, linenum);
600
		if ((fwd_port = a2port(arg)) == 0)
614
		arg2 = strdelim(&s);
601
			fatal("%.200s line %d: Bad listen port.",
615
		if (!arg2 || *arg2 == '\0')
602
			    filename, linenum);
603
		arg = strdelim(&s);
604
		if (!arg || *arg == '\0')
605
			fatal("%.200s line %d: Missing second argument.",
616
			fatal("%.200s line %d: Missing second argument.",
606
			    filename, linenum);
617
			    filename, linenum);
607
		if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 &&
618
608
		    sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
619
		/* construct a string for parse_forward */
620
		snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
621
622
		if (parse_forward(&fwd, fwdarg) == 0)
609
			fatal("%.200s line %d: Bad forwarding specification.",
623
			fatal("%.200s line %d: Bad forwarding specification.",
610
			    filename, linenum);
624
			    filename, linenum);
611
		if ((fwd_host_port = a2port(sfwd_host_port)) == 0)
625
		if (fwd.listen_port == 0)
626
			fatal("%.200s line %d: Bad listen port.",
627
			    filename, linenum);
628
		if (fwd.connect_port == 0)
612
			fatal("%.200s line %d: Bad forwarding port.",
629
			fatal("%.200s line %d: Bad forwarding port.",
613
			    filename, linenum);
630
			    filename, linenum);
631
614
		if (*activep) {
632
		if (*activep) {
615
			if (opcode == oLocalForward)
633
			if (opcode == oLocalForward)
616
				add_local_forward(options, fwd_port, buf,
634
				add_local_forward(options,
617
				    fwd_host_port);
635
				    fwd.listen_host, fwd.listen_port,
636
				    fwd.connect_host, fwd.connect_port);
618
			else if (opcode == oRemoteForward)
637
			else if (opcode == oRemoteForward)
619
				add_remote_forward(options, fwd_port, buf,
638
				add_remote_forward(options,
620
				    fwd_host_port);
639
				    fwd.listen_host, fwd.listen_port,
640
				    fwd.connect_host, fwd.connect_port);
621
		}
641
		}
622
		break;
642
		break;
623
643
Lines 626-637 Link Here
626
		if (!arg || *arg == '\0')
646
		if (!arg || *arg == '\0')
627
			fatal("%.200s line %d: Missing port argument.",
647
			fatal("%.200s line %d: Missing port argument.",
628
			    filename, linenum);
648
			    filename, linenum);
629
		fwd_port = a2port(arg);
649
		fwd.listen_port = 0;
630
		if (fwd_port == 0)
650
		fwd.listen_host = hpdelim(&arg);
651
		if (!fwd.listen_host)
652
			fatal("%.200s line %d: Bad forwarding specification.",
653
			    filename, linenum);
654
		if (arg) {
655
			fwd.listen_port = a2port(arg);
656
			fwd.listen_host = cleanhostname(fwd.listen_host);
657
		} else {
658
			fwd.listen_port = a2port(fwd.listen_host);
659
			fwd.listen_host = "";
660
		}
661
		if (fwd.listen_port == 0)
631
			fatal("%.200s line %d: Badly formatted port number.",
662
			fatal("%.200s line %d: Badly formatted port number.",
632
			    filename, linenum);
663
			    filename, linenum);
633
		if (*activep)
664
		if (*activep)
634
			add_local_forward(options, fwd_port, "socks4", 0);
665
			add_local_forward(options, fwd.listen_host,
666
			    fwd.listen_port, "socks4", 0);
635
		break;
667
		break;
636
668
637
	case oClearAllForwardings:
669
	case oClearAllForwardings:
Lines 921-924 Link Here
921
	/* options->hostname will be set in the main program if appropriate */
953
	/* options->hostname will be set in the main program if appropriate */
922
	/* options->host_key_alias should not be set by default */
954
	/* options->host_key_alias should not be set by default */
923
	/* options->preferred_authentications will be set in ssh */
955
	/* options->preferred_authentications will be set in ssh */
956
}
957
958
/*
959
 * parse_forward
960
 * parses a string containing a port forwarding specification of the form:
961
 *	[listenhost:]listenport:connecthost:connectport
962
 * returns number of arguments parsed or zero on error
963
 */
964
int
965
parse_forward(Forward *fwd, const char *fwdspec)
966
{
967
	int i;
968
	char *p, *cp, *fwdarg[4];
969
970
	cp = p = xstrdup(fwdspec);
971
972
	/* skip leading spaces */
973
	while (*cp && isspace(*cp))
974
		cp++;
975
976
	for (i = 0; i < 4; ++i)
977
		if ( !(fwdarg[i] = hpdelim(&cp)) )
978
			break;
979
	switch(i) {
980
	case 3:
981
		fwd->listen_host = NULL;
982
		fwd->listen_port = a2port(fwdarg[0]);
983
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
984
		fwd->connect_port = a2port(fwdarg[2]);
985
		break;
986
987
	case 4:
988
		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
989
		fwd->listen_port = a2port(fwdarg[1]);
990
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
991
		fwd->connect_port = a2port(fwdarg[3]);
992
		break;
993
	default:
994
		i = 0; /* failure */
995
	}
996
997
	xfree(p);
998
999
	if (fwd->listen_port == 0 && fwd->connect_port == 0)
1000
		i = 0;	/* failure */
1001
1002
	return(i);
924
}
1003
}
(-)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 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
		log("Warning: remote port forwarding failed for listen port %d",
1045
		log("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