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

Collapse All | Expand All

(-)auth-options.c (-11 / +15 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 236-260 auth_parse_options(struct passwd *pw, ch Link Here
236
			if (!*opts) {
236
			if (!*opts) {
237
				debug("%.100s, line %lu: missing end quote",
237
				debug("%.100s, line %lu: missing end quote",
238
				    file, linenum);
238
				    file, linenum);
239
				auth_debug_add("%.100s, line %lu: missing end quote",
239
				auth_debug_add("%.100s, line %lu: missing "
240
				    file, linenum);
240
				    "end quote", file, linenum);
241
				xfree(patterns);
241
				xfree(patterns);
242
				goto bad_option;
242
				goto bad_option;
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
				debug("%.100s, line %lu: Bad permitopen specification "
248
			if (host == NULL || strlen(host) >= NI_MAXHOST) {
249
				    "<%.100s>", file, linenum, patterns);
249
				debug("%.100s, line %lu: Bad permitopen "
250
				    "specification <%.100s>", file, linenum, 
251
				    patterns);
250
				auth_debug_add("%.100s, line %lu: "
252
				auth_debug_add("%.100s, line %lu: "
251
				    "Bad permitopen specification", file, linenum);
253
				    "Bad permitopen specification", file,
254
				    linenum);
252
				xfree(patterns);
255
				xfree(patterns);
253
				goto bad_option;
256
				goto bad_option;
254
			}
257
			}
255
			if ((port = a2port(sport)) == 0) {
258
 			host = cleanhostname(host);
256
				debug("%.100s, line %lu: Bad permitopen port <%.100s>",
259
 			if (p == NULL || (port = a2port(p)) == 0) {
257
				    file, linenum, sport);
260
				debug("%.100s, line %lu: Bad permitopen port "
261
				    "<%.100s>", file, linenum, p ? p : "");
258
				auth_debug_add("%.100s, line %lu: "
262
				auth_debug_add("%.100s, line %lu: "
259
				    "Bad permitopen port", file, linenum);
263
				    "Bad permitopen port", file, linenum);
260
				xfree(patterns);
264
				xfree(patterns);
(-)channels.c (-14 / +58 lines)
Lines 2173-2184 channel_setup_fwd_listener(int type, con Link Here
2173
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2173
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2174
{
2174
{
2175
	Channel *c;
2175
	Channel *c;
2176
	int success, sock, on = 1;
2176
	int sock, r, success = 0, on = 1, wildcard = 0;
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
2180
2181
	success = 0;
2182
	host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
2181
	host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
2183
	    listen_addr : host_to_connect;
2182
	    listen_addr : host_to_connect;
2184
2183
Lines 2192-2207 channel_setup_fwd_listener(int type, con Link Here
2192
	}
2191
	}
2193
2192
2194
	/*
2193
	/*
2194
	 * Determine whether or not a port forward listens to loopback,
2195
	 * specified address or wildcard.
2196
	 *
2197
	 * Special-case listen_addrs are:
2198
	 *
2199
	 * "" (empty string), "*"  -> wildcard v4/v6 (AI_PASSIVE)
2200
	 * "localhost"             -> loopback v4/v6
2201
	 */
2202
	if (gateway_ports) {
2203
		if (listen_addr == NULL || listen_addr[0] == '\0' ||
2204
		    strcmp(listen_addr, "*") == 0)
2205
			wildcard = 1;
2206
		else if (strcmp(listen_addr, "localhost") != 0)
2207
			addr = listen_addr;
2208
	} else if (type == SSH_CHANNEL_PORT_LISTENER) {
2209
		/* A client may override GatewayPorts with a wildcard */
2210
		if (listen_addr != NULL && strcmp(listen_addr, "*") == 0)
2211
			wildcard = 1;
2212
		else
2213
			addr = listen_addr;
2214
	}
2215
2216
	debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s",
2217
	    type, wildcard, (addr == NULL) ? "NULL" : addr);
2218
2219
	/*
2195
	 * getaddrinfo returns a loopback address if the hostname is
2220
	 * getaddrinfo returns a loopback address if the hostname is
2196
	 * set to NULL and hints.ai_flags is not AI_PASSIVE
2221
	 * set to NULL and hints.ai_flags is not AI_PASSIVE
2197
	 */
2222
	 */
2198
	memset(&hints, 0, sizeof(hints));
2223
	memset(&hints, 0, sizeof(hints));
2199
	hints.ai_family = IPv4or6;
2224
	hints.ai_family = IPv4or6;
2200
	hints.ai_flags = gateway_ports ? AI_PASSIVE : 0;
2225
	hints.ai_flags = wildcard ? AI_PASSIVE : 0;
2201
	hints.ai_socktype = SOCK_STREAM;
2226
	hints.ai_socktype = SOCK_STREAM;
2202
	snprintf(strport, sizeof strport, "%d", listen_port);
2227
	snprintf(strport, sizeof strport, "%d", listen_port);
2203
	if (getaddrinfo(NULL, strport, &hints, &aitop) != 0)
2228
	if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
2204
		packet_disconnect("getaddrinfo: fatal error");
2229
		if (addr == NULL) {
2230
			/* This really shouldn't happen */
2231
			packet_disconnect("getaddrinfo: fatal error: %s",
2232
			    gai_strerror(r));
2233
		} else {
2234
			verbose("channel_setup_fwd_listener: "
2235
			    "getaddrinfo(%.64s): %s", addr, gai_strerror(r));
2236
			packet_send_debug("channel_setup_fwd_listener: "
2237
			    "getaddrinfo(%.64s): %s", addr, gai_strerror(r));
2238
		}
2239
		aitop = NULL;
2240
	}
2205
2241
2206
	for (ai = aitop; ai; ai = ai->ai_next) {
2242
	for (ai = aitop; ai; ai = ai->ai_next) {
2207
		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
2243
		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
Lines 2280-2290 channel_cancel_rport_listener(const char Link Here
2280
2316
2281
/* protocol local port fwd, used by ssh (and sshd in v1) */
2317
/* protocol local port fwd, used by ssh (and sshd in v1) */
2282
int
2318
int
2283
channel_setup_local_fwd_listener(u_short listen_port,
2319
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)
2320
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2285
{
2321
{
2286
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2322
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2287
	    NULL, listen_port, host_to_connect, port_to_connect, gateway_ports);
2323
	    listen_host, listen_port, host_to_connect, port_to_connect,
2324
	    gateway_ports);
2288
}
2325
}
2289
2326
2290
/* protocol v2 remote port fwd, used by sshd */
2327
/* protocol v2 remote port fwd, used by sshd */
Lines 2302-2308 channel_setup_remote_fwd_listener(const Link Here
2302
 */
2339
 */
2303
2340
2304
void
2341
void
2305
channel_request_remote_forwarding(u_short listen_port,
2342
channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
2306
    const char *host_to_connect, u_short port_to_connect)
2343
    const char *host_to_connect, u_short port_to_connect)
2307
{
2344
{
2308
	int type, success = 0;
2345
	int type, success = 0;
Lines 2313-2319 channel_request_remote_forwarding(u_shor Link Here
2313
2350
2314
	/* Send the forward request to the remote side. */
2351
	/* Send the forward request to the remote side. */
2315
	if (compat20) {
2352
	if (compat20) {
2316
		const char *address_to_bind = "0.0.0.0";
2353
		const char *address_to_bind;
2354
		if (listen_host == NULL)
2355
			address_to_bind = "localhost";
2356
		else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0)
2357
			address_to_bind = "";
2358
		else
2359
			address_to_bind = listen_host;
2360
2317
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
2361
		packet_start(SSH2_MSG_GLOBAL_REQUEST);
2318
		packet_put_cstring("tcpip-forward");
2362
		packet_put_cstring("tcpip-forward");
2319
		packet_put_char(1);			/* boolean: want reply */
2363
		packet_put_char(1);			/* boolean: want reply */
Lines 2359-2368 channel_request_remote_forwarding(u_shor Link Here
2359
 * local side.
2403
 * local side.
2360
 */
2404
 */
2361
void
2405
void
2362
channel_request_rforward_cancel(u_short port)
2406
channel_request_rforward_cancel(const char *host, u_short port)
2363
{
2407
{
2364
	int i;
2408
	int i;
2365
	const char *address_to_bind = "0.0.0.0";
2366
2409
2367
	if (!compat20)
2410
	if (!compat20)
2368
		return;
2411
		return;
Lines 2379-2385 channel_request_rforward_cancel(u_short Link Here
2379
	packet_start(SSH2_MSG_GLOBAL_REQUEST);
2422
	packet_start(SSH2_MSG_GLOBAL_REQUEST);
2380
	packet_put_cstring("cancel-tcpip-forward");
2423
	packet_put_cstring("cancel-tcpip-forward");
2381
	packet_put_char(0);
2424
	packet_put_char(0);
2382
	packet_put_cstring(address_to_bind);
2425
	packet_put_cstring(host == NULL ? "" : host);
2383
	packet_put_int(port);
2426
	packet_put_int(port);
2384
	packet_send();
2427
	packet_send();
2385
2428
Lines 2418-2424 channel_input_port_forward_request(int i Link Here
2418
		packet_disconnect("Dynamic forwarding denied.");
2461
		packet_disconnect("Dynamic forwarding denied.");
2419
2462
2420
	/* Initiate forwarding */
2463
	/* Initiate forwarding */
2421
	channel_setup_local_fwd_listener(port, hostname, host_port, gateway_ports);
2464
	channel_setup_local_fwd_listener(NULL, port, hostname,
2465
	    host_port, gateway_ports);
2422
2466
2423
	/* Free the argument string. */
2467
	/* Free the argument string. */
2424
	xfree(hostname);
2468
	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 (+42 lines)
Lines 269-274 convtime(const char *s) Link Here
269
	return total;
269
	return total;
270
}
270
}
271
271
272
/*
273
 * Search for next delimiter between hostnames/addresses and ports.
274
 * Argument may be modified (for termination).
275
 * Returns *cp if parsing succeeds.
276
 * *cp is set to the start of the next delimiter, if one was found.
277
 * If this is the last field, *cp is set to NULL.
278
 */
279
char *
280
hpdelim(char **cp)
281
{
282
	char *s, *old;
283
284
	if (cp == NULL || *cp == NULL)
285
		return NULL;
286
287
	old = s = *cp;
288
	if (*s == '[') {
289
		if ((s = strchr(s, ']')) == NULL)
290
			return NULL;
291
		else
292
			s++;
293
	} else if ((s = strpbrk(s, ":/")) == NULL)
294
		s = *cp + strlen(*cp); /* skip to end (see first case below) */
295
296
	switch (*s) {
297
	case '\0':
298
		*cp = NULL;	/* no more fields*/
299
		break;
300
	
301
	case ':':
302
	case '/':
303
		*s = '\0';	/* terminate */
304
		*cp = s + 1;
305
		break;
306
	
307
	default:
308
		return NULL;
309
	}
310
311
	return old;
312
}
313
272
char *
314
char *
273
cleanhostname(char *host)
315
cleanhostname(char *host)
274
{
316
{
(-)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 (-37 / +118 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 Forward *newfwd)
210
		  u_short host_port)
211
{
210
{
212
	Forward *fwd;
211
	Forward *fwd;
213
	extern uid_t original_real_uid;
212
	extern uid_t original_real_uid;
214
	if (port < IPPORT_RESERVED && original_real_uid != 0)
213
	if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
215
		fatal("Privileged ports can only be forwarded by root.");
214
		fatal("Privileged ports can only be forwarded by root.");
216
	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
215
	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
217
		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
216
		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
218
	fwd = &options->local_forwards[options->num_local_forwards++];
217
	fwd = &options->local_forwards[options->num_local_forwards++];
219
	fwd->port = port;
218
220
	fwd->host = xstrdup(host);
219
	fwd->listen_host = (newfwd->listen_host == NULL) ?
221
	fwd->host_port = host_port;
220
	    NULL : xstrdup(newfwd->listen_host);
221
	fwd->listen_port = newfwd->listen_port;
222
	fwd->connect_host = xstrdup(newfwd->connect_host);
223
	fwd->connect_port = newfwd->connect_port;
222
}
224
}
223
225
224
/*
226
/*
Lines 227-243 add_local_forward(Options *options, u_sh Link Here
227
 */
229
 */
228
230
229
void
231
void
230
add_remote_forward(Options *options, u_short port, const char *host,
232
add_remote_forward(Options *options, const Forward *newfwd)
231
		   u_short host_port)
232
{
233
{
233
	Forward *fwd;
234
	Forward *fwd;
234
	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
235
	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
235
		fatal("Too many remote forwards (max %d).",
236
		fatal("Too many remote forwards (max %d).",
236
		    SSH_MAX_FORWARDS_PER_DIRECTION);
237
		    SSH_MAX_FORWARDS_PER_DIRECTION);
237
	fwd = &options->remote_forwards[options->num_remote_forwards++];
238
	fwd = &options->remote_forwards[options->num_remote_forwards++];
238
	fwd->port = port;
239
239
	fwd->host = xstrdup(host);
240
	fwd->listen_host = (newfwd->listen_host == NULL) ?
240
	fwd->host_port = host_port;
241
	    NULL : xstrdup(newfwd->listen_host);
242
	fwd->listen_port = newfwd->listen_port;
243
	fwd->connect_host = xstrdup(newfwd->connect_host);
244
	fwd->connect_port = newfwd->connect_port;
241
}
245
}
242
246
243
static void
247
static void
Lines 245-255 clear_forwardings(Options *options) Link Here
245
{
249
{
246
	int i;
250
	int i;
247
251
248
	for (i = 0; i < options->num_local_forwards; i++)
252
	for (i = 0; i < options->num_local_forwards; i++) {
249
		xfree(options->local_forwards[i].host);
253
		xfree(options->local_forwards[i].listen_host);
254
		xfree(options->local_forwards[i].connect_host);
255
	}
250
	options->num_local_forwards = 0;
256
	options->num_local_forwards = 0;
251
	for (i = 0; i < options->num_remote_forwards; i++)
257
	for (i = 0; i < options->num_remote_forwards; i++) {
252
		xfree(options->remote_forwards[i].host);
258
		xfree(options->remote_forwards[i].listen_host);
259
		xfree(options->remote_forwards[i].connect_host);
260
	}
253
	options->num_remote_forwards = 0;
261
	options->num_remote_forwards = 0;
254
}
262
}
255
263
Lines 282-292 process_config_line(Options *options, co Link Here
282
		    char *line, const char *filename, int linenum,
290
		    char *line, const char *filename, int linenum,
283
		    int *activep)
291
		    int *activep)
284
{
292
{
285
	char buf[256], *s, **charptr, *endofnumber, *keyword, *arg;
293
	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
286
	int opcode, *intptr, value;
294
	int opcode, *intptr, value;
287
	size_t len;
295
	size_t len;
288
	u_short fwd_port, fwd_host_port;
296
	Forward fwd;
289
	char sfwd_host_port[6];
290
297
291
	/* Strip trailing whitespace */
298
	/* Strip trailing whitespace */
292
	for(len = strlen(line) - 1; len > 0; len--) {
299
	for(len = strlen(line) - 1; len > 0; len--) {
Lines 643-672 parse_int: Link Here
643
	case oLocalForward:
650
	case oLocalForward:
644
	case oRemoteForward:
651
	case oRemoteForward:
645
		arg = strdelim(&s);
652
		arg = strdelim(&s);
646
		if (!arg || *arg == '\0')
653
		if (arg == NULL || *arg == '\0')
647
			fatal("%.200s line %d: Missing port argument.",
654
			fatal("%.200s line %d: Missing port argument.",
648
			    filename, linenum);
655
			    filename, linenum);
649
		if ((fwd_port = a2port(arg)) == 0)
656
		arg2 = strdelim(&s);
650
			fatal("%.200s line %d: Bad listen port.",
657
		if (arg2 == NULL || *arg2 == '\0')
658
			fatal("%.200s line %d: Missing target argument.",
651
			    filename, linenum);
659
			    filename, linenum);
652
		arg = strdelim(&s);
660
653
		if (!arg || *arg == '\0')
661
		/* construct a string for parse_forward */
654
			fatal("%.200s line %d: Missing second argument.",
662
		snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
655
			    filename, linenum);
663
656
		if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 &&
664
		if (parse_forward(&fwd, fwdarg) == 0)
657
		    sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
658
			fatal("%.200s line %d: Bad forwarding specification.",
665
			fatal("%.200s line %d: Bad forwarding specification.",
659
			    filename, linenum);
666
			    filename, linenum);
660
		if ((fwd_host_port = a2port(sfwd_host_port)) == 0)
667
661
			fatal("%.200s line %d: Bad forwarding port.",
662
			    filename, linenum);
663
		if (*activep) {
668
		if (*activep) {
664
			if (opcode == oLocalForward)
669
			if (opcode == oLocalForward)
665
				add_local_forward(options, fwd_port, buf,
670
				add_local_forward(options, &fwd);
666
				    fwd_host_port);
667
			else if (opcode == oRemoteForward)
671
			else if (opcode == oRemoteForward)
668
				add_remote_forward(options, fwd_port, buf,
672
				add_remote_forward(options, &fwd);
669
				    fwd_host_port);
670
		}
673
		}
671
		break;
674
		break;
672
675
Lines 675-686 parse_int: Link Here
675
		if (!arg || *arg == '\0')
678
		if (!arg || *arg == '\0')
676
			fatal("%.200s line %d: Missing port argument.",
679
			fatal("%.200s line %d: Missing port argument.",
677
			    filename, linenum);
680
			    filename, linenum);
678
		fwd_port = a2port(arg);
681
		memset(&fwd, '\0', sizeof(fwd));
679
		if (fwd_port == 0)
682
		fwd.connect_host = "socks";
683
		fwd.listen_host = hpdelim(&arg);
684
		if (fwd.listen_host == NULL ||
685
		    strlen(fwd.listen_host) >= NI_MAXHOST)
686
			fatal("%.200s line %d: Bad forwarding specification.",
687
			    filename, linenum);
688
		if (arg) {
689
			fwd.listen_port = a2port(arg);
690
			fwd.listen_host = cleanhostname(fwd.listen_host);
691
		} else {
692
			fwd.listen_port = a2port(fwd.listen_host);
693
			fwd.listen_host = "";
694
		}
695
		if (fwd.listen_port == 0)
680
			fatal("%.200s line %d: Badly formatted port number.",
696
			fatal("%.200s line %d: Badly formatted port number.",
681
			    filename, linenum);
697
			    filename, linenum);
682
		if (*activep)
698
		if (*activep)
683
			add_local_forward(options, fwd_port, "socks", 0);
699
			add_local_forward(options, &fwd);
684
		break;
700
		break;
685
701
686
	case oClearAllForwardings:
702
	case oClearAllForwardings:
Lines 1042-1045 fill_default_options(Options * options) Link Here
1042
	/* options->hostname will be set in the main program if appropriate */
1058
	/* options->hostname will be set in the main program if appropriate */
1043
	/* options->host_key_alias should not be set by default */
1059
	/* options->host_key_alias should not be set by default */
1044
	/* options->preferred_authentications will be set in ssh */
1060
	/* options->preferred_authentications will be set in ssh */
1061
}
1062
1063
/*
1064
 * parse_forward
1065
 * parses a string containing a port forwarding specification of the form:
1066
 *	[listenhost:]listenport:connecthost:connectport
1067
 * returns number of arguments parsed or zero on error
1068
 */
1069
int
1070
parse_forward(Forward *fwd, const char *fwdspec)
1071
{
1072
	int i;
1073
	char *p, *cp, *fwdarg[4];
1074
1075
	memset(fwd, '\0', sizeof(*fwd));
1076
1077
	cp = p = xstrdup(fwdspec);
1078
1079
	/* skip leading spaces */
1080
	while (*cp && isspace(*cp))
1081
		cp++;
1082
1083
	for (i = 0; i < 4; ++i)
1084
		if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1085
			break;
1086
1087
	/* Check for trailing garbage in 4-arg case*/
1088
	if (cp != NULL)
1089
		i = 0;	/* failure */
1090
1091
	switch (i) {
1092
	case 3:
1093
		fwd->listen_host = NULL;
1094
		fwd->listen_port = a2port(fwdarg[0]);
1095
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1096
		fwd->connect_port = a2port(fwdarg[2]);
1097
		break;
1098
1099
	case 4:
1100
		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1101
		fwd->listen_port = a2port(fwdarg[1]);
1102
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1103
		fwd->connect_port = a2port(fwdarg[3]);
1104
		break;
1105
	default:
1106
		i = 0; /* failure */
1107
	}
1108
1109
	xfree(p);
1110
1111
	if (fwd->listen_port == 0 && fwd->connect_port == 0)
1112
		goto fail_free;
1113
1114
	if (fwd->connect_host != NULL &&
1115
	    strlen(fwd->connect_host) >= NI_MAXHOST)
1116
		goto fail_free;
1117
1118
	return (i);
1119
1120
 fail_free:
1121
	if (fwd->connect_host != NULL)
1122
		xfree(fwd->connect_host);
1123
	if (fwd->listen_host != NULL)
1124
		xfree(fwd->listen_host);
1125
	return (0);
1045
}
1126
}
(-)readconf.h (-5 / +7 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	 add_local_forward(Options *, const Forward *);
125
void	 add_remote_forward(Options *, u_short, const char *, u_short);
127
void	 add_remote_forward(Options *, const Forward *);
126
128
127
#endif				/* READCONF_H */
129
#endif				/* READCONF_H */
(-)servconf.c (-32 / +15 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
	u_short 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 == NULL || *arg == '\0')
475
			fatal("%s line %d: missing inet addr.",
476
			fatal("%s line %d: missing address",
476
			    filename, linenum);
477
		if (*arg == '[') {
478
			if ((p = strchr(arg, ']')) == NULL)
479
				fatal("%s line %d: bad ipv6 inet addr usage.",
480
				    filename, linenum);
481
			arg++;
482
			memmove(p, p+1, strlen(p+1)+1);
483
		} else if (((p = strchr(arg, ':')) == NULL) ||
484
			    (strchr(p+1, ':') != NULL)) {
485
			add_listen_addr(options, arg, 0);
486
			break;
487
		}
488
		if (*p == ':') {
489
			u_short port;
490
491
			p++;
492
			if (*p == '\0')
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);
477
			    filename, linenum);
478
		p = hpdelim(&arg);
479
		if (p == NULL)
480
			fatal("%s line %d: bad address:port usage",
481
			    filename, linenum);
482
		p = cleanhostname(p);
483
		if (arg == NULL)
484
			port = 0;
485
		else if ((port = a2port(arg)) == 0)
486
			fatal("%s line %d: bad port number", filename, linenum);
487
488
		add_listen_addr(options, p, port);
489
507
		break;
490
		break;
508
491
509
	case sAddressFamily:
492
	case sAddressFamily:
(-)ssh.1 (-5 / +25 lines)
Lines 69-74 Link Here
69
.Ek
69
.Ek
70
.Oo Fl R Xo
70
.Oo Fl R Xo
71
.Sm off
71
.Sm off
72
.Oo Ar bind_address : Oc
72
.Ar port :
73
.Ar port :
73
.Ar host :
74
.Ar host :
74
.Ar hostport
75
.Ar hostport
Lines 724-729 Quiet mode. Link Here
724
Causes all warning and diagnostic messages to be suppressed.
725
Causes all warning and diagnostic messages to be suppressed.
725
.It Fl R Xo
726
.It Fl R Xo
726
.Sm off
727
.Sm off
728
.Oo bind_address : Oc
727
.Ar port : host : hostport
729
.Ar port : host : hostport
728
.Sm on
730
.Sm on
729
.Xc
731
.Xc
Lines 738-753 made to Link Here
738
port
740
port
739
.Ar hostport
741
.Ar hostport
740
from the local machine.
742
from the local machine.
743
.Pp
741
Port forwardings can also be specified in the configuration file.
744
Port forwardings can also be specified in the configuration file.
742
Privileged ports can be forwarded only when
745
Privileged ports can be forwarded only when
743
logging in as root on the remote machine.
746
logging in as root on the remote machine.
744
IPv6 addresses can be specified with an alternative syntax:
747
IPv6 addresses can be specified by enclosing the address in square braces or
745
.Sm off
748
using an alternative syntax:
746
.Xo
749
.Xo
747
.Ar port No / Ar host No /
750
.Sm off
748
.Ar hostport .
751
.Oo Ar bind_address / Oc
749
.Xc
752
.Ar host/port/hostport
750
.Sm on
753
.Sm on
754
.Xc .
755
.Pp
756
By default, the listening socket on the server will be bound to the loopback
757
interface only.
758
This may be overriden by specifying a
759
.Ar bind_address .
760
An empty 
761
.Ar bind_address , 
762
or the address
763
.Ql *
764
indicates that the remote socket should listen on all interfaces.
765
Specifying a remote
766
.Ar bind_address
767
will only succeed if the server's 
768
.Cm GatewayPorts 
769
option is enabled (see
770
.Xr sshd_config 5 ).
751
.It Fl S Ar ctl_path
771
.It Fl S Ar ctl_path
752
Specifies the location of a control socket for connection sharing.
772
Specifies the location of a control socket for connection sharing.
753
Refer to the description of
773
Refer to the description of
(-)ssh.c (-44 / +67 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
	char sfwd_port[6], sfwd_host_port[6];
183
	char *p, *cp, *line, buf[256];
182
	char *p, *cp, *line, buf[256];
184
	struct stat st;
183
	struct stat st;
185
	struct passwd *pw;
184
	struct passwd *pw;
186
	int dummy;
185
	int dummy;
187
	extern int optind, optreset;
186
	extern int optind, optreset;
188
	extern char *optarg;
187
	extern char *optarg;
188
	Forward fwd;
189
189
190
	/*
190
	/*
191
	 * Save the original real uid.  It will be needed later (uid-swapping
191
	 * Save the original real uid.  It will be needed later (uid-swapping
Lines 395-433 again: Link Here
395
			break;
395
			break;
396
396
397
		case 'L':
397
		case 'L':
398
		case 'R':
398
			if (parse_forward(&fwd, optarg))
399
			if (sscanf(optarg, "%5[0-9]:%255[^:]:%5[0-9]",
399
				add_local_forward(&options, &fwd);
400
			    sfwd_port, buf, sfwd_host_port) != 3 &&
400
			else {
401
			    sscanf(optarg, "%5[0-9]/%255[^/]/%5[0-9]",
402
			    sfwd_port, buf, sfwd_host_port) != 3) {
403
				fprintf(stderr,
401
				fprintf(stderr,
404
				    "Bad forwarding specification '%s'\n",
402
				    "Bad local forwarding specification '%s'\n",
405
				    optarg);
403
				    optarg);
406
				usage();
404
				exit(1);
407
				/* NOTREACHED */
408
			}
405
			}
409
			if ((fwd_port = a2port(sfwd_port)) == 0 ||
406
			break;
410
			    (fwd_host_port = a2port(sfwd_host_port)) == 0) {
407
408
		case 'R':
409
			if (parse_forward(&fwd, optarg)) {
410
				add_remote_forward(&options, &fwd);
411
			} else {
411
				fprintf(stderr,
412
				fprintf(stderr,
412
				    "Bad forwarding port(s) '%s'\n", optarg);
413
				    "Bad remote forwarding specification "
414
				    "'%s'\n", optarg);
413
				exit(1);
415
				exit(1);
414
			}
416
			}
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;
417
			break;
422
418
423
		case 'D':
419
		case 'D':
424
			fwd_port = a2port(optarg);
420
			cp = p = xstrdup(optarg);
425
			if (fwd_port == 0) {
421
			memset(&fwd, '\0', sizeof(fwd));
422
			fwd.connect_host = "socks";
423
			if ((fwd.listen_host = hpdelim(&cp)) == NULL) {
424
				fprintf(stderr, "Bad dynamic forwarding "
425
				    "specification '%.100s'\n", optarg);
426
				exit(1);
427
			}
428
			if (cp != NULL) {
429
				fwd.listen_port = a2port(cp);
430
				fwd.listen_host = cleanhostname(fwd.listen_host);
431
			} else {
432
				fwd.listen_port = a2port(fwd.listen_host);
433
				fwd.listen_host = "";
434
			}
435
436
			if (fwd.listen_port == 0) {
426
				fprintf(stderr, "Bad dynamic port '%s'\n",
437
				fprintf(stderr, "Bad dynamic port '%s'\n",
427
				    optarg);
438
				    optarg);
428
				exit(1);
439
				exit(1);
429
			}
440
			}
430
			add_local_forward(&options, fwd_port, "socks", 0);
441
			add_local_forward(&options, &fwd);
442
			xfree(p);
431
			break;
443
			break;
432
444
433
		case 'C':
445
		case 'C':
Lines 827-843 ssh_init_forwarding(void) Link Here
827
{
839
{
828
	int success = 0;
840
	int success = 0;
829
	int i;
841
	int i;
842
	char *listen_host;
830
843
831
	/* Initiate local TCP/IP port forwardings. */
844
	/* Initiate local TCP/IP port forwardings. */
832
	for (i = 0; i < options.num_local_forwards; i++) {
845
	for (i = 0; i < options.num_local_forwards; i++) {
833
		debug("Connections to local port %d forwarded to remote address %.200s:%d",
846
		listen_host = options.local_forwards[i].listen_host;
834
		    options.local_forwards[i].port,
847
		if (listen_host != NULL && !options.gateway_ports &&
835
		    options.local_forwards[i].host,
848
		    (listen_host[0] == '\0' || strcmp(listen_host, "*") == 0))
836
		    options.local_forwards[i].host_port);
849
			listen_host = NULL; /* localhost */
850
		debug("Local connections to %.200s:%d forwarded to remote "
851
		    "address %.200s:%d",
852
		    (listen_host == NULL) ? "LOCALHOST" : listen_host,
853
		    options.local_forwards[i].listen_port,
854
		    options.local_forwards[i].connect_host,
855
		    options.local_forwards[i].connect_port);
837
		success += channel_setup_local_fwd_listener(
856
		success += channel_setup_local_fwd_listener(
838
		    options.local_forwards[i].port,
857
		    listen_host,
839
		    options.local_forwards[i].host,
858
		    options.local_forwards[i].listen_port,
840
		    options.local_forwards[i].host_port,
859
		    options.local_forwards[i].connect_host,
860
		    options.local_forwards[i].connect_port,
841
		    options.gateway_ports);
861
		    options.gateway_ports);
842
	}
862
	}
843
	if (i > 0 && success == 0)
863
	if (i > 0 && success == 0)
Lines 845-858 ssh_init_forwarding(void) Link Here
845
865
846
	/* Initiate remote TCP/IP port forwardings. */
866
	/* Initiate remote TCP/IP port forwardings. */
847
	for (i = 0; i < options.num_remote_forwards; i++) {
867
	for (i = 0; i < options.num_remote_forwards; i++) {
848
		debug("Connections to remote port %d forwarded to local address %.200s:%d",
868
		debug("Remote connections from %.200s:%d forwarded to "
849
		    options.remote_forwards[i].port,
869
		    "local address %.200s:%d",
850
		    options.remote_forwards[i].host,
870
		    options.remote_forwards[i].listen_host,
851
		    options.remote_forwards[i].host_port);
871
		    options.remote_forwards[i].listen_port,
872
		    options.remote_forwards[i].connect_host,
873
		    options.remote_forwards[i].connect_port);
852
		channel_request_remote_forwarding(
874
		channel_request_remote_forwarding(
853
		    options.remote_forwards[i].port,
875
		    options.remote_forwards[i].listen_host,
854
		    options.remote_forwards[i].host,
876
		    options.remote_forwards[i].listen_port,
855
		    options.remote_forwards[i].host_port);
877
		    options.remote_forwards[i].connect_host,
878
		    options.remote_forwards[i].connect_port);
856
	}
879
	}
857
}
880
}
858
881
Lines 1028-1039 client_global_request_reply_fwd(int type Link Here
1028
		return;
1051
		return;
1029
	debug("remote forward %s for: listen %d, connect %s:%d",
1052
	debug("remote forward %s for: listen %d, connect %s:%d",
1030
	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1053
	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1031
	    options.remote_forwards[i].port,
1054
	    options.remote_forwards[i].listen_port,
1032
	    options.remote_forwards[i].host,
1055
	    options.remote_forwards[i].connect_host,
1033
	    options.remote_forwards[i].host_port);
1056
	    options.remote_forwards[i].connect_port);
1034
	if (type == SSH2_MSG_REQUEST_FAILURE)
1057
	if (type == SSH2_MSG_REQUEST_FAILURE)
1035
		logit("Warning: remote port forwarding failed for listen port %d",
1058
		logit("Warning: remote port forwarding failed for listen "
1036
		    options.remote_forwards[i].port);
1059
		    "port %d", options.remote_forwards[i].listen_port);
1037
}
1060
}
1038
1061
1039
static void
1062
static void
(-)ssh_config.5 (-3 / +30 lines)
Lines 587-598 This option applies to protocol version Link Here
587
Specifies that a TCP/IP port on the remote machine be forwarded over
587
Specifies that a TCP/IP port on the remote machine be forwarded over
588
the secure channel to the specified host and port from the local machine.
588
the secure channel to the specified host and port from the local machine.
589
The first argument must be a port number, and the second must be
589
The first argument must be a port number, and the second must be
590
.Ar host:port .
590
.Xo
591
IPv6 addresses can be specified with an alternative syntax:
591
.Sm off
592
.Ar host/port .
592
.Oo Ar bind_address : Oc
593
.Ar host:port
594
.Sm on
595
.Xc .
596
IPv6 addresses can be specified by enclosing any addresses in square brackets
597
or by using the alternative syntax:
598
.Xo
599
.Sm off
600
.Oo Ar bind_address / Oc
601
.Ar host/port
602
.Sm on
603
.Xc .
593
Multiple forwardings may be specified, and additional
604
Multiple forwardings may be specified, and additional
594
forwardings can be given on the command line.
605
forwardings can be given on the command line.
595
Only the superuser can forward privileged ports.
606
Only the superuser can forward privileged ports.
607
.Pp
608
If the
609
.Ar bind_address
610
is not specified, the default is to only bind to loopback addresses.
611
If the
612
.Ar bind_address
613
is
614
.Ql *
615
or an empty string, then the forwarding is requested to listen on all
616
interfaces.
617
Specifying a remote
618
.Ar bind_address
619
will only succeed if the server's 
620
.Cm GatewayPorts 
621
option is enabled (see
622
.Xr sshd_config 5 ).
596
.It Cm RhostsRSAAuthentication
623
.It Cm RhostsRSAAuthentication
597
Specifies whether to try rhosts based authentication with RSA host
624
Specifies whether to try rhosts based authentication with RSA host
598
authentication.
625
authentication.
(-)sshd_config.5 (-2 / +2 lines)
Lines 256-263 This prevents other remote hosts from co Link Here
256
.Cm GatewayPorts
256
.Cm GatewayPorts
257
can be used to specify that
257
can be used to specify that
258
.Nm sshd
258
.Nm sshd
259
should bind remote port forwardings to the wildcard address,
259
should allow remote port forwardings to bind to non-loopback addresses, thus
260
thus allowing remote hosts to connect to forwarded ports.
260
allowing other hosts to connect.
261
The argument must be
261
The argument must be
262
.Dq yes
262
.Dq yes
263
or
263
or

Return to bug 413