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 (-12 / +39 lines)
Lines 2175-2182 Link Here
2175
	Channel *c;
2175
	Channel *c;
2176
	int success, sock, on = 1;
2176
	int success, sock, on = 1;
2177
	struct addrinfo hints, *ai, *aitop;
2177
	struct addrinfo hints, *ai, *aitop;
2178
	const char *host;
2178
	const char *host, *addr = NULL;
2179
	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2179
	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2180
	int wildcard = 0;
2180
2181
2181
	success = 0;
2182
	success = 0;
2182
	host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
2183
	host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
Lines 2192-2207 Link Here
2192
	}
2193
	}
2193
2194
2194
	/*
2195
	/*
2196
	 * Determine whether or not a port forward listens to loopback,
2197
	 * specified address or wildcard.
2198
	 */
2199
	if (gateway_ports) {
2200
		if (listen_addr == NULL || listen_addr[0] == '\0' ||
2201
		    strcmp(listen_addr, "*") == 0)
2202
				wildcard = 1;
2203
			else
2204
				addr = listen_addr;
2205
	} else if (type == SSH_CHANNEL_PORT_LISTENER) {
2206
		/* A client may override GatewayPorts with a wildcard */
2207
		if (listen_addr != NULL && strcmp(listen_addr, "*") == 0)
2208
			wildcard = 1;
2209
		else
2210
			addr = listen_addr;
2211
	}
2212
2213
	/*
2195
	 * getaddrinfo returns a loopback address if the hostname is
2214
	 * getaddrinfo returns a loopback address if the hostname is
2196
	 * set to NULL and hints.ai_flags is not AI_PASSIVE
2215
	 * set to NULL and hints.ai_flags is not AI_PASSIVE
2197
	 */
2216
	 */
2198
	memset(&hints, 0, sizeof(hints));
2217
	memset(&hints, 0, sizeof(hints));
2199
	hints.ai_family = IPv4or6;
2218
	hints.ai_family = IPv4or6;
2200
	hints.ai_flags = gateway_ports ? AI_PASSIVE : 0;
2219
	hints.ai_flags = wildcard ? AI_PASSIVE : 0;
2201
	hints.ai_socktype = SOCK_STREAM;
2220
	hints.ai_socktype = SOCK_STREAM;
2202
	snprintf(strport, sizeof strport, "%d", listen_port);
2221
	snprintf(strport, sizeof strport, "%d", listen_port);
2203
	if (getaddrinfo(NULL, strport, &hints, &aitop) != 0)
2222
	if (getaddrinfo(addr, strport, &hints, &aitop) != 0)
2204
		packet_disconnect("getaddrinfo: fatal error");
2223
		packet_disconnect("getaddrinfo: %.200s: fatal error",
2224
		    addr ? addr : "(NULL)");
2205
2225
2206
	for (ai = aitop; ai; ai = ai->ai_next) {
2226
	for (ai = aitop; ai; ai = ai->ai_next) {
2207
		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
2227
		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
Lines 2279-2289 Link Here
2279
2299
2280
/* protocol local port fwd, used by ssh (and sshd in v1) */
2300
/* protocol local port fwd, used by ssh (and sshd in v1) */
2281
int
2301
int
2282
channel_setup_local_fwd_listener(u_short listen_port,
2302
channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,
2283
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2303
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2284
{
2304
{
2285
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2305
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2286
	    NULL, listen_port, host_to_connect, port_to_connect, gateway_ports);
2306
	    listen_host, listen_port, host_to_connect, port_to_connect,
2307
	    gateway_ports);
2287
}
2308
}
2288
2309
2289
/* protocol v2 remote port fwd, used by sshd */
2310
/* protocol v2 remote port fwd, used by sshd */
Lines 2301-2307 Link Here
2301
 */
2322
 */
2302
2323
2303
void
2324
void
2304
channel_request_remote_forwarding(u_short listen_port,
2325
channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
2305
    const char *host_to_connect, u_short port_to_connect)
2326
    const char *host_to_connect, u_short port_to_connect)
2306
{
2327
{
2307
	int type, success = 0;
2328
	int type, success = 0;
Lines 2312-2318 Link Here
2312
2333
2313
	/* Send the forward request to the remote side. */
2334
	/* Send the forward request to the remote side. */
2314
	if (compat20) {
2335
	if (compat20) {
2315
		const char *address_to_bind = "0.0.0.0";
2336
		const char *address_to_bind;
2337
		if (listen_host == NULL)
2338
			address_to_bind = "127.0.0.1";
2339
		else if (listen_host[0] == '\0' || strcmp(listen_host, "*")==0)
2340
			address_to_bind = "0.0.0.0";
2341
		else
2342
			address_to_bind = listen_host;
2343
2316
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
2344
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
2317
		packet_put_cstring("tcpip-forward");
2345
		packet_put_cstring("tcpip-forward");
2318
		packet_put_char(1);			/* boolean: want reply */
2346
		packet_put_char(1);			/* boolean: want reply */
Lines 2359-2368 Link Here
2359
 */
2387
 */
2360
2388
2361
void
2389
void
2362
channel_request_rforward_cancel(u_short port)
2390
channel_request_rforward_cancel(const char *host, u_short port)
2363
{
2391
{
2364
	int i;
2392
	int i;
2365
	const char *address_to_bind = "0.0.0.0";
2366
2393
2367
	if (!compat20)
2394
	if (!compat20)
2368
		return;
2395
		return;
Lines 2379-2385 Link Here
2379
	packet_start(SSH2_MSG_GLOBAL_REQUEST);
2406
	packet_start(SSH2_MSG_GLOBAL_REQUEST);
2380
	packet_put_cstring("cancel-tcpip-forward");
2407
	packet_put_cstring("cancel-tcpip-forward");
2381
	packet_put_char(0);
2408
	packet_put_char(0);
2382
	packet_put_cstring(address_to_bind);
2409
	packet_put_cstring(host == NULL ? "0.0.0.0" : host);
2383
	packet_put_int(port);
2410
	packet_put_int(port);
2384
	packet_send();
2411
	packet_send();
2385
2412
Lines 2418-2424 Link Here
2418
		packet_disconnect("Dynamic forwarding denied.");
2445
		packet_disconnect("Dynamic forwarding denied.");
2419
2446
2420
	/* Initiate forwarding */
2447
	/* Initiate forwarding */
2421
	channel_setup_local_fwd_listener(port, hostname, host_port, gateway_ports);
2448
	channel_setup_local_fwd_listener(NULL, port, hostname, host_port, gateway_ports);
2422
2449
2423
	/* Free the argument string. */
2450
	/* Free the argument string. */
2424
	xfree(hostname);
2451
	xfree(hostname);
(-)channels.h (-3 / +5 lines)
Lines 201-209 Link Here
201
void     channel_input_port_forward_request(int, int);
201
void     channel_input_port_forward_request(int, int);
202
int	 channel_connect_to(const char *, u_short);
202
int	 channel_connect_to(const char *, u_short);
203
int	 channel_connect_by_listen_address(u_short);
203
int	 channel_connect_by_listen_address(u_short);
204
void	 channel_request_remote_forwarding(u_short, const char *, u_short);
204
void	 channel_request_remote_forwarding(const char *, u_short,
205
void	 channel_request_rforward_cancel(u_short port);
205
	     const char *, u_short);
206
int	 channel_setup_local_fwd_listener(u_short, const char *, u_short, int);
206
int	 channel_setup_local_fwd_listener(const char *, u_short,
207
	     const char *, u_short, int);
208
void	 channel_request_rforward_cancel(const char *host, u_short port);
207
int	 channel_setup_remote_fwd_listener(const char *, u_short, int);
209
int	 channel_setup_remote_fwd_listener(const char *, u_short, int);
208
int	 channel_cancel_rport_listener(const char *, u_short);
210
int	 channel_cancel_rport_listener(const char *, u_short);
209
211
(-)clientloop.c (-23 / +24 lines)
Lines 732-742 Link Here
732
process_cmdline(void)
732
process_cmdline(void)
733
{
733
{
734
	void (*handler)(int);
734
	void (*handler)(int);
735
	char *s, *cmd;
735
	char *s, *cmd, *cancel_host;
736
	u_short fwd_port, fwd_host_port;
737
	char buf[1024], sfwd_port[6], sfwd_host_port[6];
738
	int delete = 0;
736
	int delete = 0;
739
	int local = 0;
737
	int local = 0;
738
	u_short cancel_port;
739
	Forward fwd;
740
740
741
	leave_raw_mode();
741
	leave_raw_mode();
742
	handler = signal(SIGINT, SIG_IGN);
742
	handler = signal(SIGINT, SIG_IGN);
Lines 782-818 Link Here
782
		s++;
782
		s++;
783
783
784
	if (delete) {
784
	if (delete) {
785
		if (sscanf(s, "%5[0-9]", sfwd_host_port) != 1) {
785
		cancel_port = 0;
786
			logit("Bad forwarding specification.");
786
		cancel_host = hpdelim(&s);	/* may be NULL */
787
			goto out;
787
		if (s != NULL) {
788
			cancel_port = a2port(s);
789
			cancel_host = cleanhostname(cancel_host);
790
		} else {
791
			cancel_port = a2port(cancel_host);
792
			cancel_host = NULL;
788
		}
793
		}
789
		if ((fwd_host_port = a2port(sfwd_host_port)) == 0) {
794
		if (cancel_port == 0) {
790
			logit("Bad forwarding port(s).");
795
			logit("Bad forwarding close port");
791
			goto out;
796
			goto out;
792
		}
797
		}
793
		channel_request_rforward_cancel(fwd_host_port);
798
		channel_request_rforward_cancel(cancel_host, cancel_port);
794
	} else {
799
	} else {
795
		if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]",
800
		if (!parse_forward(&fwd, s)) {
796
		    sfwd_port, buf, sfwd_host_port) != 3 &&
797
		    sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]",
798
		    sfwd_port, buf, sfwd_host_port) != 3) {
799
			logit("Bad forwarding specification.");
801
			logit("Bad forwarding specification.");
800
			goto out;
802
			goto out;
801
		}
803
		}
802
		if ((fwd_port = a2port(sfwd_port)) == 0 ||
803
		    (fwd_host_port = a2port(sfwd_host_port)) == 0) {
804
			logit("Bad forwarding port(s).");
805
			goto out;
806
		}
807
		if (local) {
804
		if (local) {
808
			if (channel_setup_local_fwd_listener(fwd_port, buf,
805
			if (channel_setup_local_fwd_listener(fwd.listen_host,
809
			    fwd_host_port, options.gateway_ports) < 0) {
806
			    fwd.listen_port, fwd.connect_host,
807
			    fwd.connect_port, options.gateway_ports) < 0) {
810
				logit("Port forwarding failed.");
808
				logit("Port forwarding failed.");
811
				goto out;
809
				goto out;
812
			}
810
			}
813
		} else
811
		} else {
814
			channel_request_remote_forwarding(fwd_port, buf,
812
			channel_request_remote_forwarding(fwd.listen_host,
815
			    fwd_host_port);
813
			    fwd.listen_port, fwd.connect_host,
814
			    fwd.connect_port);
815
		}
816
816
		logit("Forwarding port.");
817
		logit("Forwarding port.");
817
	}
818
	}
818
819
(-)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 20-25 Link Here
20
int	 unset_nonblock(int);
20
int	 unset_nonblock(int);
21
void	 set_nodelay(int);
21
void	 set_nodelay(int);
22
int	 a2port(const char *);
22
int	 a2port(const char *);
23
char	*hpdelim(char **);
23
char	*cleanhostname(char *);
24
char	*cleanhostname(char *);
24
char	*colon(char *);
25
char	*colon(char *);
25
long	 convtime(const char *);
26
long	 convtime(const char *);
(-)readconf.c (-33 / +109 lines)
Lines 206-224 Link Here
206
 */
206
 */
207
207
208
void
208
void
209
add_local_forward(Options *options, u_short port, const char *host,
209
add_local_forward(Options *options, const char *listen_host,
210
		  u_short host_port)
210
    u_short listen_port, const char *connect_host, u_short connect_port)
211
{
211
{
212
	Forward *fwd;
212
	Forward *fwd;
213
	extern uid_t original_real_uid;
213
	extern uid_t original_real_uid;
214
	if (port < IPPORT_RESERVED && original_real_uid != 0)
214
	if (listen_port < IPPORT_RESERVED && original_real_uid != 0)
215
		fatal("Privileged ports can only be forwarded by root.");
215
		fatal("Privileged ports can only be forwarded by root.");
216
	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
216
	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
217
		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
217
		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
218
	fwd = &options->local_forwards[options->num_local_forwards++];
218
	fwd = &options->local_forwards[options->num_local_forwards++];
219
	fwd->port = port;
219
	if (listen_host == NULL)
220
	fwd->host = xstrdup(host);
220
		fwd->listen_host = NULL;
221
	fwd->host_port = host_port;
221
	else
222
		fwd->listen_host = xstrdup(listen_host);
223
	fwd->listen_port = listen_port;
224
	fwd->connect_host = xstrdup(connect_host);
225
	fwd->connect_port = connect_port;
222
}
226
}
223
227
224
/*
228
/*
Lines 227-243 Link Here
227
 */
231
 */
228
232
229
void
233
void
230
add_remote_forward(Options *options, u_short port, const char *host,
234
add_remote_forward(Options *options, const char *listen_host,
231
		   u_short host_port)
235
    u_short listen_port, const char *connect_host, u_short connect_port)
232
{
236
{
233
	Forward *fwd;
237
	Forward *fwd;
234
	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
238
	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
235
		fatal("Too many remote forwards (max %d).",
239
		fatal("Too many remote forwards (max %d).",
236
		    SSH_MAX_FORWARDS_PER_DIRECTION);
240
		    SSH_MAX_FORWARDS_PER_DIRECTION);
237
	fwd = &options->remote_forwards[options->num_remote_forwards++];
241
	fwd = &options->remote_forwards[options->num_remote_forwards++];
238
	fwd->port = port;
242
	if (listen_host == NULL)
239
	fwd->host = xstrdup(host);
243
		fwd->listen_host = NULL;
240
	fwd->host_port = host_port;
244
	else
245
		fwd->listen_host = xstrdup(listen_host);
246
	fwd->listen_port = listen_port;
247
	fwd->connect_host = xstrdup(connect_host);
248
	fwd->connect_port = connect_port;
241
}
249
}
242
250
243
static void
251
static void
Lines 245-255 Link Here
245
{
253
{
246
	int i;
254
	int i;
247
255
248
	for (i = 0; i < options->num_local_forwards; i++)
256
	for (i = 0; i < options->num_local_forwards; i++) {
249
		xfree(options->local_forwards[i].host);
257
		xfree(options->local_forwards[i].listen_host);
258
		xfree(options->local_forwards[i].connect_host);
259
	}
250
	options->num_local_forwards = 0;
260
	options->num_local_forwards = 0;
251
	for (i = 0; i < options->num_remote_forwards; i++)
261
	for (i = 0; i < options->num_remote_forwards; i++) {
252
		xfree(options->remote_forwards[i].host);
262
		xfree(options->remote_forwards[i].listen_host);
263
		xfree(options->remote_forwards[i].connect_host);
264
	}
253
	options->num_remote_forwards = 0;
265
	options->num_remote_forwards = 0;
254
}
266
}
255
267
Lines 282-292 Link Here
282
		    char *line, const char *filename, int linenum,
294
		    char *line, const char *filename, int linenum,
283
		    int *activep)
295
		    int *activep)
284
{
296
{
285
	char buf[256], *s, **charptr, *endofnumber, *keyword, *arg;
297
	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
286
	int opcode, *intptr, value;
298
	int opcode, *intptr, value;
287
	size_t len;
299
	size_t len;
288
	u_short fwd_port, fwd_host_port;
300
	Forward fwd;
289
	char sfwd_host_port[6];
290
301
291
	/* Strip trailing whitespace */
302
	/* Strip trailing whitespace */
292
	for(len = strlen(line) - 1; len > 0; len--) {
303
	for(len = strlen(line) - 1; len > 0; len--) {
Lines 646-672 Link Here
646
		if (!arg || *arg == '\0')
657
		if (!arg || *arg == '\0')
647
			fatal("%.200s line %d: Missing port argument.",
658
			fatal("%.200s line %d: Missing port argument.",
648
			    filename, linenum);
659
			    filename, linenum);
649
		if ((fwd_port = a2port(arg)) == 0)
660
		arg2 = strdelim(&s);
650
			fatal("%.200s line %d: Bad listen port.",
661
		if (!arg2 || *arg2 == '\0')
651
			    filename, linenum);
652
		arg = strdelim(&s);
653
		if (!arg || *arg == '\0')
654
			fatal("%.200s line %d: Missing second argument.",
662
			fatal("%.200s line %d: Missing second argument.",
655
			    filename, linenum);
663
			    filename, linenum);
656
		if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 &&
664
657
		    sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
665
		/* construct a string for parse_forward */
666
		snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
667
668
		if (parse_forward(&fwd, fwdarg) == 0)
658
			fatal("%.200s line %d: Bad forwarding specification.",
669
			fatal("%.200s line %d: Bad forwarding specification.",
659
			    filename, linenum);
670
			    filename, linenum);
660
		if ((fwd_host_port = a2port(sfwd_host_port)) == 0)
671
		if (fwd.listen_port == 0)
672
			fatal("%.200s line %d: Bad listen port.",
673
			    filename, linenum);
674
		if (fwd.connect_port == 0)
661
			fatal("%.200s line %d: Bad forwarding port.",
675
			fatal("%.200s line %d: Bad forwarding port.",
662
			    filename, linenum);
676
			    filename, linenum);
677
663
		if (*activep) {
678
		if (*activep) {
664
			if (opcode == oLocalForward)
679
			if (opcode == oLocalForward)
665
				add_local_forward(options, fwd_port, buf,
680
				add_local_forward(options,
666
				    fwd_host_port);
681
				    fwd.listen_host, fwd.listen_port,
682
				    fwd.connect_host, fwd.connect_port);
667
			else if (opcode == oRemoteForward)
683
			else if (opcode == oRemoteForward)
668
				add_remote_forward(options, fwd_port, buf,
684
				add_remote_forward(options,
669
				    fwd_host_port);
685
				    fwd.listen_host, fwd.listen_port,
686
				    fwd.connect_host, fwd.connect_port);
670
		}
687
		}
671
		break;
688
		break;
672
689
Lines 675-686 Link Here
675
		if (!arg || *arg == '\0')
692
		if (!arg || *arg == '\0')
676
			fatal("%.200s line %d: Missing port argument.",
693
			fatal("%.200s line %d: Missing port argument.",
677
			    filename, linenum);
694
			    filename, linenum);
678
		fwd_port = a2port(arg);
695
		fwd.listen_port = 0;
679
		if (fwd_port == 0)
696
		fwd.listen_host = hpdelim(&arg);
697
		if (!fwd.listen_host)
698
			fatal("%.200s line %d: Bad forwarding specification.",
699
			    filename, linenum);
700
		if (arg) {
701
			fwd.listen_port = a2port(arg);
702
			fwd.listen_host = cleanhostname(fwd.listen_host);
703
		} else {
704
			fwd.listen_port = a2port(fwd.listen_host);
705
			fwd.listen_host = "";
706
		}
707
		if (fwd.listen_port == 0)
680
			fatal("%.200s line %d: Badly formatted port number.",
708
			fatal("%.200s line %d: Badly formatted port number.",
681
			    filename, linenum);
709
			    filename, linenum);
682
		if (*activep)
710
		if (*activep)
683
			add_local_forward(options, fwd_port, "socks", 0);
711
			add_local_forward(options, fwd.listen_host,
712
			    fwd.listen_port, "socks4", 0);
684
		break;
713
		break;
685
714
686
	case oClearAllForwardings:
715
	case oClearAllForwardings:
Lines 1042-1045 Link Here
1042
	/* options->hostname will be set in the main program if appropriate */
1071
	/* options->hostname will be set in the main program if appropriate */
1043
	/* options->host_key_alias should not be set by default */
1072
	/* options->host_key_alias should not be set by default */
1044
	/* options->preferred_authentications will be set in ssh */
1073
	/* options->preferred_authentications will be set in ssh */
1074
}
1075
1076
/*
1077
 * parse_forward
1078
 * parses a string containing a port forwarding specification of the form:
1079
 *	[listenhost:]listenport:connecthost:connectport
1080
 * returns number of arguments parsed or zero on error
1081
 */
1082
int
1083
parse_forward(Forward *fwd, const char *fwdspec)
1084
{
1085
	int i;
1086
	char *p, *cp, *fwdarg[4];
1087
1088
	cp = p = xstrdup(fwdspec);
1089
1090
	/* skip leading spaces */
1091
	while (*cp && isspace(*cp))
1092
		cp++;
1093
1094
	for (i = 0; i < 4; ++i)
1095
		if ( !(fwdarg[i] = hpdelim(&cp)) )
1096
			break;
1097
	switch(i) {
1098
	case 3:
1099
		fwd->listen_host = NULL;
1100
		fwd->listen_port = a2port(fwdarg[0]);
1101
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1102
		fwd->connect_port = a2port(fwdarg[2]);
1103
		break;
1104
1105
	case 4:
1106
		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1107
		fwd->listen_port = a2port(fwdarg[1]);
1108
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1109
		fwd->connect_port = a2port(fwdarg[3]);
1110
		break;
1111
	default:
1112
		i = 0; /* failure */
1113
	}
1114
1115
	xfree(p);
1116
1117
	if (fwd->listen_port == 0 && fwd->connect_port == 0)
1118
		i = 0;	/* failure */
1119
1120
	return(i);
1045
}
1121
}
(-)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 117-127 Link Here
117
void     initialize_options(Options *);
118
void     initialize_options(Options *);
118
void     fill_default_options(Options *);
119
void     fill_default_options(Options *);
119
int	 read_config_file(const char *, const char *, Options *, int);
120
int	 read_config_file(const char *, const char *, Options *, int);
121
int	 parse_forward(Forward *, const char *);
120
122
121
int
123
int
122
process_config_line(Options *, const char *, char *, const char *, int, int *);
124
process_config_line(Options *, const char *, char *, const char *, int, int *);
123
125
124
void	 add_local_forward(Options *, u_short, const char *, u_short);
126
void
125
void	 add_remote_forward(Options *, u_short, const char *, u_short);
127
add_local_forward(Options *, const char *, u_short, const char *, u_short);
128
void
129
add_remote_forward(Options *, const char *, u_short, const char *, u_short);
126
130
127
#endif				/* READCONF_H */
131
#endif				/* READCONF_H */
(-)servconf.c (-28 / +17 lines)
Lines 402-407 Link Here
402
	char *cp, **charptr, *arg, *p;
402
	char *cp, **charptr, *arg, *p;
403
	int *intptr, value, i, n;
403
	int *intptr, value, i, n;
404
	ServerOpCodes opcode;
404
	ServerOpCodes opcode;
405
	ushort port;
405
406
406
	cp = line;
407
	cp = line;
407
	arg = strdelim(&cp);
408
	arg = strdelim(&cp);
Lines 468-506 Link Here
468
469
469
	case sListenAddress:
470
	case sListenAddress:
470
		arg = strdelim(&cp);
471
		arg = strdelim(&cp);
471
		if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
472
		if (!arg || *arg == '\0')
472
			fatal("%s line %d: missing inet addr.",
473
			fatal("%s line %d: missing inet addr.",
473
			    filename, linenum);
474
			    filename, linenum);
474
		if (*arg == '[') {
475
		p = hpdelim(&arg);
475
			if ((p = strchr(arg, ']')) == NULL)
476
		if (!p)
476
				fatal("%s line %d: bad ipv6 inet addr usage.",
477
			fatal("%s line %d: bad inet addr:port usage.",
478
			    filename, linenum);
479
		p = cleanhostname(p);
480
		if (arg) {
481
			port = a2port(arg);
482
			if (port == 0) {
483
				fatal("%s line %d: bad port number.",
477
				    filename, linenum);
484
				    filename, linenum);
478
			arg++;
485
				/* NOTREACHED */
479
			memmove(p, p+1, strlen(p+1)+1);
486
			}
480
		} else if (((p = strchr(arg, ':')) == NULL) ||
487
		} else {
481
			    (strchr(p+1, ':') != NULL)) {
488
			port = 0;
482
			add_listen_addr(options, arg, 0);
483
			break;
484
		}
489
		}
485
		if (*p == ':') {
486
			u_short port;
487
490
488
			p++;
491
		add_listen_addr(options, p, port);
489
			if (*p == '\0')
492
490
				fatal("%s line %d: bad inet addr:port usage.",
491
				    filename, linenum);
492
			else {
493
				*(p-1) = '\0';
494
				if ((port = a2port(p)) == 0)
495
					fatal("%s line %d: bad port number.",
496
					    filename, linenum);
497
				add_listen_addr(options, arg, port);
498
			}
499
		} else if (*p == '\0')
500
			add_listen_addr(options, arg, 0);
501
		else
502
			fatal("%s line %d: bad inet addr usage.",
503
			    filename, linenum);
504
		break;
493
		break;
505
494
506
	case sHostKeyFile:
495
	case sHostKeyFile:
(-)ssh.c (-43 / +71 lines)
Lines 148-162 Link Here
148
u_int control_server_pid = 0;
148
u_int control_server_pid = 0;
149
149
150
/* Prints a help message to the user.  This function never returns. */
150
/* Prints a help message to the user.  This function never returns. */
151
static void usage(void) __dead;
151
152
152
static void
153
static void
153
usage(void)
154
usage(void)
154
{
155
{
155
	fprintf(stderr,
156
	fprintf(stderr,
156
"usage: ssh [-1246AaCfghkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
157
"usage: ssh [-1246AaCfghkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
157
"           [-D port] [-e escape_char] [-F configfile] [-i identity_file]\n"
158
"           [-D [listen-host:]port] [-e escape_char] [-F configfile]\n"
158
"           [-L port:host:hostport] [-l login_name] [-m mac_spec] [-o option]\n"
159
"           [-i identity_file] [-L [listen-host:]port:host:hostport]\n"
159
"           [-p port] [-R port:host:hostport] [-S ctl] [user@]hostname [command]\n"
160
"           [-l login_name][-m mac_spec] [-o option] [-p port]\n"
161
"           [-R [listen-host:]port:host:hostport] [-S ctl]\n"
162
"           [user@]hostname [command]\n"
160
	);
163
	);
161
	exit(1);
164
	exit(1);
162
}
165
}
Lines 173-186 Link Here
173
main(int ac, char **av)
176
main(int ac, char **av)
174
{
177
{
175
	int i, opt, exit_status;
178
	int i, opt, exit_status;
176
	u_short fwd_port, fwd_host_port;
179
	u_short fwd_lport;
177
	char sfwd_port[6], sfwd_host_port[6];
180
	char *fwd_lhost;
178
	char *p, *cp, *line, buf[256];
181
	char *p, *cp, *line, buf[256];
179
	struct stat st;
182
	struct stat st;
180
	struct passwd *pw;
183
	struct passwd *pw;
181
	int dummy;
184
	int dummy;
182
	extern int optind, optreset;
185
	extern int optind, optreset;
183
	extern char *optarg;
186
	extern char *optarg;
187
	Forward fwd;
184
188
185
	/*
189
	/*
186
	 * Save the original real uid.  It will be needed later (uid-swapping
190
	 * Save the original real uid.  It will be needed later (uid-swapping
Lines 382-420 Link Here
382
			break;
386
			break;
383
387
384
		case 'L':
388
		case 'L':
385
		case 'R':
389
			if (parse_forward(&fwd, optarg)) {
386
			if (sscanf(optarg, "%5[0-9]:%255[^:]:%5[0-9]",
390
				add_local_forward(&options,
387
			    sfwd_port, buf, sfwd_host_port) != 3 &&
391
				    fwd.listen_host, fwd.listen_port,
388
			    sscanf(optarg, "%5[0-9]/%255[^/]/%5[0-9]",
392
				    fwd.connect_host, fwd.connect_port);
389
			    sfwd_port, buf, sfwd_host_port) != 3) {
393
			} else {
390
				fprintf(stderr,
394
				fprintf(stderr,
391
				    "Bad forwarding specification '%s'\n",
395
				    "Bad forwarding specification '%s'\n",
392
				    optarg);
396
				    optarg);
393
				usage();
397
				usage();
394
				/* NOTREACHED */
395
			}
398
			}
396
			if ((fwd_port = a2port(sfwd_port)) == 0 ||
399
			break;
397
			    (fwd_host_port = a2port(sfwd_host_port)) == 0) {
400
401
		case 'R':
402
			if (parse_forward(&fwd, optarg)) {
403
				add_remote_forward(&options,
404
				    fwd.listen_host, fwd.listen_port,
405
				    fwd.connect_host, fwd.connect_port);
406
			} else {
398
				fprintf(stderr,
407
				fprintf(stderr,
399
				    "Bad forwarding port(s) '%s'\n", optarg);
408
				    "Bad forwarding specification '%s'\n",
400
				exit(1);
409
				    optarg);
410
				usage();
401
			}
411
			}
402
			if (opt == 'L')
403
				add_local_forward(&options, fwd_port, buf,
404
				    fwd_host_port);
405
			else if (opt == 'R')
406
				add_remote_forward(&options, fwd_port, buf,
407
				    fwd_host_port);
408
			break;
412
			break;
409
413
410
		case 'D':
414
		case 'D':
411
			fwd_port = a2port(optarg);
415
			cp = p = xstrdup(optarg);
412
			if (fwd_port == 0) {
416
			fwd_lport = 0;
417
			fwd_lhost = hpdelim(&cp);	/* may be NULL */
418
			if (cp != NULL) {
419
				fwd_lport = a2port(cp);
420
				fwd_lhost = cleanhostname(fwd_lhost);
421
			} else {
422
				fwd_lport = a2port(fwd_lhost);
423
				fwd_lhost = "";
424
			}
425
426
			if (fwd_lport == 0) {
413
				fprintf(stderr, "Bad dynamic port '%s'\n",
427
				fprintf(stderr, "Bad dynamic port '%s'\n",
414
				    optarg);
428
				    optarg);
415
				exit(1);
429
				xfree(p);
430
				usage();
416
			}
431
			}
417
			add_local_forward(&options, fwd_port, "socks", 0);
432
			add_local_forward(&options,
433
			    fwd_lhost, fwd_lport, "socks4", 0);
434
			xfree(p);
418
			break;
435
			break;
419
436
420
		case 'C':
437
		case 'C':
Lines 812-828 Link Here
812
{
829
{
813
	int success = 0;
830
	int success = 0;
814
	int i;
831
	int i;
832
	char *listen_host;
815
833
816
	/* Initiate local TCP/IP port forwardings. */
834
	/* Initiate local TCP/IP port forwardings. */
817
	for (i = 0; i < options.num_local_forwards; i++) {
835
	for (i = 0; i < options.num_local_forwards; i++) {
818
		debug("Connections to local port %d forwarded to remote address %.200s:%d",
836
		listen_host = options.local_forwards[i].listen_host;
819
		    options.local_forwards[i].port,
837
		if (listen_host && listen_host[0] == '\0' && !options.gateway_ports)
820
		    options.local_forwards[i].host,
838
			listen_host = NULL;
821
		    options.local_forwards[i].host_port);
839
		debug("Local connections to %.200s:%d forwarded to remote address %.200s:%d",
840
		    listen_host,
841
		    options.local_forwards[i].listen_port,
842
		    options.local_forwards[i].connect_host,
843
		    options.local_forwards[i].connect_port);
822
		success += channel_setup_local_fwd_listener(
844
		success += channel_setup_local_fwd_listener(
823
		    options.local_forwards[i].port,
845
		    listen_host,
824
		    options.local_forwards[i].host,
846
		    options.local_forwards[i].listen_port,
825
		    options.local_forwards[i].host_port,
847
		    options.local_forwards[i].connect_host,
848
		    options.local_forwards[i].connect_port,
826
		    options.gateway_ports);
849
		    options.gateway_ports);
827
	}
850
	}
828
	if (i > 0 && success == 0)
851
	if (i > 0 && success == 0)
Lines 830-843 Link Here
830
853
831
	/* Initiate remote TCP/IP port forwardings. */
854
	/* Initiate remote TCP/IP port forwardings. */
832
	for (i = 0; i < options.num_remote_forwards; i++) {
855
	for (i = 0; i < options.num_remote_forwards; i++) {
833
		debug("Connections to remote port %d forwarded to local address %.200s:%d",
856
		listen_host = options.remote_forwards[i].listen_host;
834
		    options.remote_forwards[i].port,
857
		if (listen_host && listen_host[0] == '\0' && !options.gateway_ports)
835
		    options.remote_forwards[i].host,
858
			listen_host = NULL;
836
		    options.remote_forwards[i].host_port);
859
		debug("Remote connections from %.200s:%d forwarded to local address %.200s:%d",
860
		    listen_host,
861
		    options.remote_forwards[i].listen_port,
862
		    options.remote_forwards[i].connect_host,
863
		    options.remote_forwards[i].connect_port);
837
		channel_request_remote_forwarding(
864
		channel_request_remote_forwarding(
838
		    options.remote_forwards[i].port,
865
		    listen_host,
839
		    options.remote_forwards[i].host,
866
		    options.remote_forwards[i].listen_port,
840
		    options.remote_forwards[i].host_port);
867
		    options.remote_forwards[i].connect_host,
868
		    options.remote_forwards[i].connect_port);
841
	}
869
	}
842
}
870
}
843
871
Lines 1013-1024 Link Here
1013
		return;
1041
		return;
1014
	debug("remote forward %s for: listen %d, connect %s:%d",
1042
	debug("remote forward %s for: listen %d, connect %s:%d",
1015
	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1043
	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1016
	    options.remote_forwards[i].port,
1044
	    options.remote_forwards[i].listen_port,
1017
	    options.remote_forwards[i].host,
1045
	    options.remote_forwards[i].connect_host,
1018
	    options.remote_forwards[i].host_port);
1046
	    options.remote_forwards[i].connect_port);
1019
	if (type == SSH2_MSG_REQUEST_FAILURE)
1047
	if (type == SSH2_MSG_REQUEST_FAILURE)
1020
		logit("Warning: remote port forwarding failed for listen port %d",
1048
		logit("Warning: remote port forwarding failed for listen port %d",
1021
		    options.remote_forwards[i].port);
1049
		    options.remote_forwards[i].listen_port);
1022
}
1050
}
1023
1051
1024
static void
1052
static void

Return to bug 413