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 / +126 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 643-672 parse_int: Link Here
643
	case oLocalForward:
654
	case oLocalForward:
644
	case oRemoteForward:
655
	case oRemoteForward:
645
		arg = strdelim(&s);
656
		arg = strdelim(&s);
646
		if (!arg || *arg == '\0')
657
		if (arg == NULL || *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 == NULL || *arg2 == '\0')
651
			    filename, linenum);
662
			fatal("%.200s line %d: Missing target argument.",
652
		arg = strdelim(&s);
653
		if (!arg || *arg == '\0')
654
			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
661
			fatal("%.200s line %d: Bad forwarding port.",
662
			    filename, linenum);
663
		if (*activep) {
672
		if (*activep) {
664
			if (opcode == oLocalForward)
673
			if (opcode == oLocalForward)
665
				add_local_forward(options, fwd_port, buf,
674
				add_local_forward(options,
666
				    fwd_host_port);
675
				    fwd.listen_host, fwd.listen_port,
676
				    fwd.connect_host, fwd.connect_port);
667
			else if (opcode == oRemoteForward)
677
			else if (opcode == oRemoteForward)
668
				add_remote_forward(options, fwd_port, buf,
678
				add_remote_forward(options,
669
				    fwd_host_port);
679
				    fwd.listen_host, fwd.listen_port,
680
				    fwd.connect_host, fwd.connect_port);
670
		}
681
		}
671
		break;
682
		break;
672
683
Lines 675-686 parse_int: Link Here
675
		if (!arg || *arg == '\0')
686
		if (!arg || *arg == '\0')
676
			fatal("%.200s line %d: Missing port argument.",
687
			fatal("%.200s line %d: Missing port argument.",
677
			    filename, linenum);
688
			    filename, linenum);
678
		fwd_port = a2port(arg);
689
		fwd.listen_port = 0;
679
		if (fwd_port == 0)
690
		fwd.listen_host = hpdelim(&arg);
691
		if (fwd.listen_host == NULL ||
692
		    strlen(fwd.listen_host) >= NI_MAXHOST)
693
			fatal("%.200s line %d: Bad forwarding specification.",
694
			    filename, linenum);
695
		if (arg) {
696
			fwd.listen_port = a2port(arg);
697
			fwd.listen_host = cleanhostname(fwd.listen_host);
698
		} else {
699
			fwd.listen_port = a2port(fwd.listen_host);
700
			fwd.listen_host = "";
701
		}
702
		if (fwd.listen_port == 0)
680
			fatal("%.200s line %d: Badly formatted port number.",
703
			fatal("%.200s line %d: Badly formatted port number.",
681
			    filename, linenum);
704
			    filename, linenum);
682
		if (*activep)
705
		if (*activep)
683
			add_local_forward(options, fwd_port, "socks", 0);
706
			add_local_forward(options, fwd.listen_host,
707
			    fwd.listen_port, "socks", 0);
684
		break;
708
		break;
685
709
686
	case oClearAllForwardings:
710
	case oClearAllForwardings:
Lines 1042-1045 fill_default_options(Options * options) Link Here
1042
	/* options->hostname will be set in the main program if appropriate */
1066
	/* options->hostname will be set in the main program if appropriate */
1043
	/* options->host_key_alias should not be set by default */
1067
	/* options->host_key_alias should not be set by default */
1044
	/* options->preferred_authentications will be set in ssh */
1068
	/* options->preferred_authentications will be set in ssh */
1069
}
1070
1071
/*
1072
 * parse_forward
1073
 * parses a string containing a port forwarding specification of the form:
1074
 *	[listenhost:]listenport:connecthost:connectport
1075
 * returns number of arguments parsed or zero on error
1076
 */
1077
int
1078
parse_forward(Forward *fwd, const char *fwdspec)
1079
{
1080
	int i;
1081
	char *p, *cp, *fwdarg[4];
1082
1083
	memset(fwd, '\0', sizeof(*fwd));
1084
1085
	cp = p = xstrdup(fwdspec);
1086
1087
	/* skip leading spaces */
1088
	while (*cp && isspace(*cp))
1089
		cp++;
1090
1091
	for (i = 0; i < 4; ++i)
1092
		if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1093
			break;
1094
1095
	/* Check for trailing garbage in 4-arg case*/
1096
	if (cp != NULL)
1097
		i = 0;	/* failure */
1098
1099
	switch (i) {
1100
	case 3:
1101
		fwd->listen_host = NULL;
1102
		fwd->listen_port = a2port(fwdarg[0]);
1103
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1104
		fwd->connect_port = a2port(fwdarg[2]);
1105
		break;
1106
1107
	case 4:
1108
		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1109
		fwd->listen_port = a2port(fwdarg[1]);
1110
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1111
		fwd->connect_port = a2port(fwdarg[3]);
1112
		break;
1113
	default:
1114
		i = 0; /* failure */
1115
	}
1116
1117
	xfree(p);
1118
1119
	if (fwd->listen_port == 0 && fwd->connect_port == 0)
1120
		goto fail_free;
1121
1122
	if (fwd->connect_host != NULL &&
1123
	    strlen(fwd->connect_host) >= NI_MAXHOST)
1124
		goto fail_free;
1125
1126
	return (i);
1127
1128
 fail_free:
1129
	if (fwd->connect_host != NULL)
1130
		xfree(fwd->connect_host);
1131
	if (fwd->listen_host != NULL)
1132
		xfree(fwd->listen_host);
1133
	return (0);
1045
}
1134
}
(-)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 (-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.c (-44 / +73 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 local forwarding specification '%s'\n",
405
				    optarg);
407
				    optarg);
406
				usage();
408
				exit(1);
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 remote forwarding specification "
420
				    "'%s'\n", optarg);
413
				exit(1);
421
				exit(1);
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
			if ((fwd_lhost = hpdelim(&cp)) == NULL) {
429
				fprintf(stderr, "Bad dynamic forwarding "
430
				    "specification '%.100s'\n", optarg);
431
				exit(1);
432
			}
433
			if (cp != NULL) {
434
				fwd_lport = a2port(cp);
435
				fwd_lhost = cleanhostname(fwd_lhost);
436
			} else {
437
				fwd_lport = a2port(fwd_lhost);
438
				fwd_lhost = "";
439
			}
440
441
			if (fwd_lport == 0) {
426
				fprintf(stderr, "Bad dynamic port '%s'\n",
442
				fprintf(stderr, "Bad dynamic port '%s'\n",
427
				    optarg);
443
				    optarg);
428
				exit(1);
444
				exit(1);
429
			}
445
			}
430
			add_local_forward(&options, fwd_port, "socks", 0);
446
			add_local_forward(&options,
447
			    fwd_lhost, fwd_lport, "socks", 0);
448
			xfree(p);
431
			break;
449
			break;
432
450
433
		case 'C':
451
		case 'C':
Lines 827-843 ssh_init_forwarding(void) Link Here
827
{
845
{
828
	int success = 0;
846
	int success = 0;
829
	int i;
847
	int i;
848
	char *listen_host;
830
849
831
	/* Initiate local TCP/IP port forwardings. */
850
	/* Initiate local TCP/IP port forwardings. */
832
	for (i = 0; i < options.num_local_forwards; i++) {
851
	for (i = 0; i < options.num_local_forwards; i++) {
833
		debug("Connections to local port %d forwarded to remote address %.200s:%d",
852
		listen_host = options.local_forwards[i].listen_host;
834
		    options.local_forwards[i].port,
853
		if (listen_host != NULL && !options.gateway_ports &&
835
		    options.local_forwards[i].host,
854
		    (listen_host[0] == '\0' || strcmp(listen_host, "*") == 0))
836
		    options.local_forwards[i].host_port);
855
			listen_host = NULL; /* localhost */
856
		debug("Local connections to %.200s:%d forwarded to remote "
857
		    "address %.200s:%d",
858
		    (listen_host == NULL) ? "LOCALHOST" : listen_host,
859
		    options.local_forwards[i].listen_port,
860
		    options.local_forwards[i].connect_host,
861
		    options.local_forwards[i].connect_port);
837
		success += channel_setup_local_fwd_listener(
862
		success += channel_setup_local_fwd_listener(
838
		    options.local_forwards[i].port,
863
		    listen_host,
839
		    options.local_forwards[i].host,
864
		    options.local_forwards[i].listen_port,
840
		    options.local_forwards[i].host_port,
865
		    options.local_forwards[i].connect_host,
866
		    options.local_forwards[i].connect_port,
841
		    options.gateway_ports);
867
		    options.gateway_ports);
842
	}
868
	}
843
	if (i > 0 && success == 0)
869
	if (i > 0 && success == 0)
Lines 845-858 ssh_init_forwarding(void) Link Here
845
871
846
	/* Initiate remote TCP/IP port forwardings. */
872
	/* Initiate remote TCP/IP port forwardings. */
847
	for (i = 0; i < options.num_remote_forwards; i++) {
873
	for (i = 0; i < options.num_remote_forwards; i++) {
848
		debug("Connections to remote port %d forwarded to local address %.200s:%d",
874
		debug("Remote connections from %.200s:%d forwarded to "
849
		    options.remote_forwards[i].port,
875
		    "local address %.200s:%d",
850
		    options.remote_forwards[i].host,
876
		    options.remote_forwards[i].listen_host,
851
		    options.remote_forwards[i].host_port);
877
		    options.remote_forwards[i].listen_port,
878
		    options.remote_forwards[i].connect_host,
879
		    options.remote_forwards[i].connect_port);
852
		channel_request_remote_forwarding(
880
		channel_request_remote_forwarding(
853
		    options.remote_forwards[i].port,
881
		    options.remote_forwards[i].listen_host,
854
		    options.remote_forwards[i].host,
882
		    options.remote_forwards[i].listen_port,
855
		    options.remote_forwards[i].host_port);
883
		    options.remote_forwards[i].connect_host,
884
		    options.remote_forwards[i].connect_port);
856
	}
885
	}
857
}
886
}
858
887
Lines 1028-1039 client_global_request_reply_fwd(int type Link Here
1028
		return;
1057
		return;
1029
	debug("remote forward %s for: listen %d, connect %s:%d",
1058
	debug("remote forward %s for: listen %d, connect %s:%d",
1030
	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1059
	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1031
	    options.remote_forwards[i].port,
1060
	    options.remote_forwards[i].listen_port,
1032
	    options.remote_forwards[i].host,
1061
	    options.remote_forwards[i].connect_host,
1033
	    options.remote_forwards[i].host_port);
1062
	    options.remote_forwards[i].connect_port);
1034
	if (type == SSH2_MSG_REQUEST_FAILURE)
1063
	if (type == SSH2_MSG_REQUEST_FAILURE)
1035
		logit("Warning: remote port forwarding failed for listen port %d",
1064
		logit("Warning: remote port forwarding failed for listen "
1036
		    options.remote_forwards[i].port);
1065
		    "port %d", options.remote_forwards[i].listen_port);
1037
}
1066
}
1038
1067
1039
static void
1068
static void

Return to bug 413