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 auth_parse_options(struct passwd *pw, ch 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 auth_parse_options(struct passwd *pw, ch 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 auth_parse_options(struct passwd *pw, ch 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 channel_setup_fwd_listener(int type, con 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 channel_setup_fwd_listener(int type, con 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 2280-2290 channel_cancel_rport_listener(const char Link Here
2280
2300
2281
/* protocol local port fwd, used by ssh (and sshd in v1) */
2301
/* protocol local port fwd, used by ssh (and sshd in v1) */
2282
int
2302
int
2283
channel_setup_local_fwd_listener(u_short listen_port,
2303
channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,
2284
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2304
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2285
{
2305
{
2286
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2306
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2287
	    NULL, listen_port, host_to_connect, port_to_connect, gateway_ports);
2307
	    listen_host, listen_port, host_to_connect, port_to_connect,
2308
	    gateway_ports);
2288
}
2309
}
2289
2310
2290
/* protocol v2 remote port fwd, used by sshd */
2311
/* protocol v2 remote port fwd, used by sshd */
Lines 2302-2308 channel_setup_remote_fwd_listener(const Link Here
2302
 */
2323
 */
2303
2324
2304
void
2325
void
2305
channel_request_remote_forwarding(u_short listen_port,
2326
channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
2306
    const char *host_to_connect, u_short port_to_connect)
2327
    const char *host_to_connect, u_short port_to_connect)
2307
{
2328
{
2308
	int type, success = 0;
2329
	int type, success = 0;
Lines 2313-2319 channel_request_remote_forwarding(u_shor Link Here
2313
2334
2314
	/* Send the forward request to the remote side. */
2335
	/* Send the forward request to the remote side. */
2315
	if (compat20) {
2336
	if (compat20) {
2316
		const char *address_to_bind = "0.0.0.0";
2337
		const char *address_to_bind;
2338
		if (listen_host == NULL)
2339
			address_to_bind = "127.0.0.1";
2340
		else if (listen_host[0] == '\0' || strcmp(listen_host, "*")==0)
2341
			address_to_bind = "0.0.0.0";
2342
		else
2343
			address_to_bind = listen_host;
2344
2317
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
2345
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
2318
		packet_put_cstring("tcpip-forward");
2346
		packet_put_cstring("tcpip-forward");
2319
		packet_put_char(1);			/* boolean: want reply */
2347
		packet_put_char(1);			/* boolean: want reply */
Lines 2359-2368 channel_request_remote_forwarding(u_shor Link Here
2359
 * local side.
2387
 * local side.
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 channel_request_rforward_cancel(u_short 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 channel_input_port_forward_request(int i 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 202-210 void channel_clear_permitted_opens(void Link Here
202
void     channel_input_port_forward_request(int, int);
202
void     channel_input_port_forward_request(int, int);
203
int	 channel_connect_to(const char *, u_short);
203
int	 channel_connect_to(const char *, u_short);
204
int	 channel_connect_by_listen_address(u_short);
204
int	 channel_connect_by_listen_address(u_short);
205
void	 channel_request_remote_forwarding(u_short, const char *, u_short);
205
void	 channel_request_remote_forwarding(const char *, u_short,
206
void	 channel_request_rforward_cancel(u_short port);
206
	     const char *, u_short);
207
int	 channel_setup_local_fwd_listener(u_short, const char *, u_short, int);
207
int	 channel_setup_local_fwd_listener(const char *, u_short,
208
	     const char *, u_short, int);
209
void	 channel_request_rforward_cancel(const char *host, u_short port);
208
int	 channel_setup_remote_fwd_listener(const char *, u_short, int);
210
int	 channel_setup_remote_fwd_listener(const char *, u_short, int);
209
int	 channel_cancel_rport_listener(const char *, u_short);
211
int	 channel_cancel_rport_listener(const char *, u_short);
210
212
(-)clientloop.c (-23 / +24 lines)
Lines 763-773 static void Link Here
763
process_cmdline(void)
763
process_cmdline(void)
764
{
764
{
765
	void (*handler)(int);
765
	void (*handler)(int);
766
	char *s, *cmd;
766
	char *s, *cmd, *cancel_host;
767
	u_short fwd_port, fwd_host_port;
768
	char buf[1024], sfwd_port[6], sfwd_host_port[6];
769
	int delete = 0;
767
	int delete = 0;
770
	int local = 0;
768
	int local = 0;
769
	u_short cancel_port;
770
	Forward fwd;
771
771
772
	leave_raw_mode();
772
	leave_raw_mode();
773
	handler = signal(SIGINT, SIG_IGN);
773
	handler = signal(SIGINT, SIG_IGN);
Lines 813-849 process_cmdline(void) Link Here
813
		s++;
813
		s++;
814
814
815
	if (delete) {
815
	if (delete) {
816
		if (sscanf(s, "%5[0-9]", sfwd_host_port) != 1) {
816
		cancel_port = 0;
817
			logit("Bad forwarding specification.");
817
		cancel_host = hpdelim(&s);	/* may be NULL */
818
			goto out;
818
		if (s != NULL) {
819
			cancel_port = a2port(s);
820
			cancel_host = cleanhostname(cancel_host);
821
		} else {
822
			cancel_port = a2port(cancel_host);
823
			cancel_host = NULL;
819
		}
824
		}
820
		if ((fwd_host_port = a2port(sfwd_host_port)) == 0) {
825
		if (cancel_port == 0) {
821
			logit("Bad forwarding port(s).");
826
			logit("Bad forwarding close port");
822
			goto out;
827
			goto out;
823
		}
828
		}
824
		channel_request_rforward_cancel(fwd_host_port);
829
		channel_request_rforward_cancel(cancel_host, cancel_port);
825
	} else {
830
	} else {
826
		if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]",
831
		if (!parse_forward(&fwd, s)) {
827
		    sfwd_port, buf, sfwd_host_port) != 3 &&
828
		    sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]",
829
		    sfwd_port, buf, sfwd_host_port) != 3) {
830
			logit("Bad forwarding specification.");
832
			logit("Bad forwarding specification.");
831
			goto out;
833
			goto out;
832
		}
834
		}
833
		if ((fwd_port = a2port(sfwd_port)) == 0 ||
834
		    (fwd_host_port = a2port(sfwd_host_port)) == 0) {
835
			logit("Bad forwarding port(s).");
836
			goto out;
837
		}
838
		if (local) {
835
		if (local) {
839
			if (channel_setup_local_fwd_listener(fwd_port, buf,
836
			if (channel_setup_local_fwd_listener(fwd.listen_host,
840
			    fwd_host_port, options.gateway_ports) < 0) {
837
			    fwd.listen_port, fwd.connect_host,
838
			    fwd.connect_port, options.gateway_ports) < 0) {
841
				logit("Port forwarding failed.");
839
				logit("Port forwarding failed.");
842
				goto out;
840
				goto out;
843
			}
841
			}
844
		} else
842
		} else {
845
			channel_request_remote_forwarding(fwd_port, buf,
843
			channel_request_remote_forwarding(fwd.listen_host,
846
			    fwd_host_port);
844
			    fwd.listen_port, fwd.connect_host,
845
			    fwd.connect_port);
846
		}
847
847
		logit("Forwarding port.");
848
		logit("Forwarding port.");
848
	}
849
	}
849
850
(-)misc.c (+45 lines)
Lines 269-274 convtime(const char *s) 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 int set_nonblock(int); 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 static struct { 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 add_local_forward(Options *options, u_sh 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 clear_forwardings(Options *options) 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 process_config_line(Options *options, co 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 parse_int: 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 parse_int: 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 fill_default_options(Options * options) 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 typedef struct { 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 405-410 process_server_config_line(ServerOptions Link Here
405
	char *cp, **charptr, *arg, *p;
405
	char *cp, **charptr, *arg, *p;
406
	int *intptr, value, i, n;
406
	int *intptr, value, i, n;
407
	ServerOpCodes opcode;
407
	ServerOpCodes opcode;
408
	ushort port;
408
409
409
	cp = line;
410
	cp = line;
410
	arg = strdelim(&cp);
411
	arg = strdelim(&cp);
Lines 471-509 parse_time: Link Here
471
472
472
	case sListenAddress:
473
	case sListenAddress:
473
		arg = strdelim(&cp);
474
		arg = strdelim(&cp);
474
		if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
475
		if (!arg || *arg == '\0')
475
			fatal("%s line %d: missing inet addr.",
476
			fatal("%s line %d: missing inet addr.",
476
			    filename, linenum);
477
			    filename, linenum);
477
		if (*arg == '[') {
478
		p = hpdelim(&arg);
478
			if ((p = strchr(arg, ']')) == NULL)
479
		if (!p)
479
				fatal("%s line %d: bad ipv6 inet addr usage.",
480
			fatal("%s line %d: bad inet addr:port usage.",
481
			    filename, linenum);
482
		p = cleanhostname(p);
483
		if (arg) {
484
			port = a2port(arg);
485
			if (port == 0) {
486
				fatal("%s line %d: bad port number.",
480
				    filename, linenum);
487
				    filename, linenum);
481
			arg++;
488
				/* NOTREACHED */
482
			memmove(p, p+1, strlen(p+1)+1);
489
			}
483
		} else if (((p = strchr(arg, ':')) == NULL) ||
490
		} else {
484
			    (strchr(p+1, ':') != NULL)) {
491
			port = 0;
485
			add_listen_addr(options, arg, 0);
486
			break;
487
		}
492
		}
488
		if (*p == ':') {
489
			u_short port;
490
493
491
			p++;
494
		add_listen_addr(options, p, port);
492
			if (*p == '\0')
495
493
				fatal("%s line %d: bad inet addr:port usage.",
494
				    filename, linenum);
495
			else {
496
				*(p-1) = '\0';
497
				if ((port = a2port(p)) == 0)
498
					fatal("%s line %d: bad port number.",
499
					    filename, linenum);
500
				add_listen_addr(options, arg, port);
501
			}
502
		} else if (*p == '\0')
503
			add_listen_addr(options, arg, 0);
504
		else
505
			fatal("%s line %d: bad inet addr usage.",
506
			    filename, linenum);
507
		break;
496
		break;
508
497
509
	case sAddressFamily:
498
	case sAddressFamily:
(-)ssh.c (-43 / +69 lines)
Lines 158-166 usage(void) Link Here
158
{
158
{
159
	fprintf(stderr,
159
	fprintf(stderr,
160
"usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
160
"usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
161
"           [-D port] [-e escape_char] [-F configfile] [-i identity_file]\n"
161
"           [-D [listen-host:]port] [-e escape_char] [-F configfile]\n"
162
"           [-L port:host:hostport] [-l login_name] [-m mac_spec] [-O ctl_cmd]\n"
162
"           [-i identity_file] [-L [listen-host:]port:host:hostport]\n"
163
"           [-o option] [-p port] [-R port:host:hostport] [-S ctl_path]\n"
163
"           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
164
"           [-R [listen-host:]port:host:hostport] [-S ctl_path]\n"
164
"           [user@]hostname [command]\n"
165
"           [user@]hostname [command]\n"
165
	);
166
	);
166
	exit(1);
167
	exit(1);
Lines 178-191 int Link Here
178
main(int ac, char **av)
179
main(int ac, char **av)
179
{
180
{
180
	int i, opt, exit_status;
181
	int i, opt, exit_status;
181
	u_short fwd_port, fwd_host_port;
182
	u_short fwd_lport;
182
	char sfwd_port[6], sfwd_host_port[6];
183
	char *fwd_lhost;
183
	char *p, *cp, *line, buf[256];
184
	char *p, *cp, *line, buf[256];
184
	struct stat st;
185
	struct stat st;
185
	struct passwd *pw;
186
	struct passwd *pw;
186
	int dummy;
187
	int dummy;
187
	extern int optind, optreset;
188
	extern int optind, optreset;
188
	extern char *optarg;
189
	extern char *optarg;
190
	Forward fwd;
189
191
190
	/*
192
	/*
191
	 * Save the original real uid.  It will be needed later (uid-swapping
193
	 * Save the original real uid.  It will be needed later (uid-swapping
Lines 395-433 again: Link Here
395
			break;
397
			break;
396
398
397
		case 'L':
399
		case 'L':
398
		case 'R':
400
			if (parse_forward(&fwd, optarg)) {
399
			if (sscanf(optarg, "%5[0-9]:%255[^:]:%5[0-9]",
401
				add_local_forward(&options,
400
			    sfwd_port, buf, sfwd_host_port) != 3 &&
402
				    fwd.listen_host, fwd.listen_port,
401
			    sscanf(optarg, "%5[0-9]/%255[^/]/%5[0-9]",
403
				    fwd.connect_host, fwd.connect_port);
402
			    sfwd_port, buf, sfwd_host_port) != 3) {
404
			} else {
403
				fprintf(stderr,
405
				fprintf(stderr,
404
				    "Bad forwarding specification '%s'\n",
406
				    "Bad forwarding specification '%s'\n",
405
				    optarg);
407
				    optarg);
406
				usage();
408
				usage();
407
				/* NOTREACHED */
408
			}
409
			}
409
			if ((fwd_port = a2port(sfwd_port)) == 0 ||
410
			break;
410
			    (fwd_host_port = a2port(sfwd_host_port)) == 0) {
411
412
		case 'R':
413
			if (parse_forward(&fwd, optarg)) {
414
				add_remote_forward(&options,
415
				    fwd.listen_host, fwd.listen_port,
416
				    fwd.connect_host, fwd.connect_port);
417
			} else {
411
				fprintf(stderr,
418
				fprintf(stderr,
412
				    "Bad forwarding port(s) '%s'\n", optarg);
419
				    "Bad forwarding specification '%s'\n",
413
				exit(1);
420
				    optarg);
421
				usage();
414
			}
422
			}
415
			if (opt == 'L')
416
				add_local_forward(&options, fwd_port, buf,
417
				    fwd_host_port);
418
			else if (opt == 'R')
419
				add_remote_forward(&options, fwd_port, buf,
420
				    fwd_host_port);
421
			break;
423
			break;
422
424
423
		case 'D':
425
		case 'D':
424
			fwd_port = a2port(optarg);
426
			cp = p = xstrdup(optarg);
425
			if (fwd_port == 0) {
427
			fwd_lport = 0;
428
			fwd_lhost = hpdelim(&cp);	/* may be NULL */
429
			if (cp != NULL) {
430
				fwd_lport = a2port(cp);
431
				fwd_lhost = cleanhostname(fwd_lhost);
432
			} else {
433
				fwd_lport = a2port(fwd_lhost);
434
				fwd_lhost = "";
435
			}
436
437
			if (fwd_lport == 0) {
426
				fprintf(stderr, "Bad dynamic port '%s'\n",
438
				fprintf(stderr, "Bad dynamic port '%s'\n",
427
				    optarg);
439
				    optarg);
428
				exit(1);
440
				xfree(p);
441
				usage();
429
			}
442
			}
430
			add_local_forward(&options, fwd_port, "socks", 0);
443
			add_local_forward(&options,
444
			    fwd_lhost, fwd_lport, "socks4", 0);
445
			xfree(p);
431
			break;
446
			break;
432
447
433
		case 'C':
448
		case 'C':
Lines 827-843 ssh_init_forwarding(void) Link Here
827
{
842
{
828
	int success = 0;
843
	int success = 0;
829
	int i;
844
	int i;
845
	char *listen_host;
830
846
831
	/* Initiate local TCP/IP port forwardings. */
847
	/* Initiate local TCP/IP port forwardings. */
832
	for (i = 0; i < options.num_local_forwards; i++) {
848
	for (i = 0; i < options.num_local_forwards; i++) {
833
		debug("Connections to local port %d forwarded to remote address %.200s:%d",
849
		listen_host = options.local_forwards[i].listen_host;
834
		    options.local_forwards[i].port,
850
		if (listen_host && listen_host[0] == '\0' && !options.gateway_ports)
835
		    options.local_forwards[i].host,
851
			listen_host = NULL;
836
		    options.local_forwards[i].host_port);
852
		debug("Local connections to %.200s:%d forwarded to remote address %.200s:%d",
853
		    listen_host,
854
		    options.local_forwards[i].listen_port,
855
		    options.local_forwards[i].connect_host,
856
		    options.local_forwards[i].connect_port);
837
		success += channel_setup_local_fwd_listener(
857
		success += channel_setup_local_fwd_listener(
838
		    options.local_forwards[i].port,
858
		    listen_host,
839
		    options.local_forwards[i].host,
859
		    options.local_forwards[i].listen_port,
840
		    options.local_forwards[i].host_port,
860
		    options.local_forwards[i].connect_host,
861
		    options.local_forwards[i].connect_port,
841
		    options.gateway_ports);
862
		    options.gateway_ports);
842
	}
863
	}
843
	if (i > 0 && success == 0)
864
	if (i > 0 && success == 0)
Lines 845-858 ssh_init_forwarding(void) Link Here
845
866
846
	/* Initiate remote TCP/IP port forwardings. */
867
	/* Initiate remote TCP/IP port forwardings. */
847
	for (i = 0; i < options.num_remote_forwards; i++) {
868
	for (i = 0; i < options.num_remote_forwards; i++) {
848
		debug("Connections to remote port %d forwarded to local address %.200s:%d",
869
		listen_host = options.remote_forwards[i].listen_host;
849
		    options.remote_forwards[i].port,
870
		if (listen_host && listen_host[0] == '\0' && !options.gateway_ports)
850
		    options.remote_forwards[i].host,
871
			listen_host = NULL;
851
		    options.remote_forwards[i].host_port);
872
		debug("Remote connections from %.200s:%d forwarded to local address %.200s:%d",
873
		    listen_host,
874
		    options.remote_forwards[i].listen_port,
875
		    options.remote_forwards[i].connect_host,
876
		    options.remote_forwards[i].connect_port);
852
		channel_request_remote_forwarding(
877
		channel_request_remote_forwarding(
853
		    options.remote_forwards[i].port,
878
		    listen_host,
854
		    options.remote_forwards[i].host,
879
		    options.remote_forwards[i].listen_port,
855
		    options.remote_forwards[i].host_port);
880
		    options.remote_forwards[i].connect_host,
881
		    options.remote_forwards[i].connect_port);
856
	}
882
	}
857
}
883
}
858
884
Lines 1028-1039 client_global_request_reply_fwd(int type Link Here
1028
		return;
1054
		return;
1029
	debug("remote forward %s for: listen %d, connect %s:%d",
1055
	debug("remote forward %s for: listen %d, connect %s:%d",
1030
	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1056
	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1031
	    options.remote_forwards[i].port,
1057
	    options.remote_forwards[i].listen_port,
1032
	    options.remote_forwards[i].host,
1058
	    options.remote_forwards[i].connect_host,
1033
	    options.remote_forwards[i].host_port);
1059
	    options.remote_forwards[i].connect_port);
1034
	if (type == SSH2_MSG_REQUEST_FAILURE)
1060
	if (type == SSH2_MSG_REQUEST_FAILURE)
1035
		logit("Warning: remote port forwarding failed for listen port %d",
1061
		logit("Warning: remote port forwarding failed for listen port %d",
1036
		    options.remote_forwards[i].port);
1062
		    options.remote_forwards[i].listen_port);
1037
}
1063
}
1038
1064
1039
static void
1065
static void

Return to bug 413