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

Collapse All | Expand All

(-)canohost.c (-10 / +20 lines)
Lines 16-21 Link Here
16
#include <sys/socket.h>
16
#include <sys/socket.h>
17
17
18
#include <netinet/in.h>
18
#include <netinet/in.h>
19
#include <sys/un.h>
19
20
20
#include <ctype.h>
21
#include <ctype.h>
21
#include <errno.h>
22
#include <errno.h>
Lines 217-230 Link Here
217
	addrlen = sizeof(addr);
218
	addrlen = sizeof(addr);
218
	memset(&addr, 0, sizeof(addr));
219
	memset(&addr, 0, sizeof(addr));
219
220
221
	if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) < 0)
222
		return NULL;
223
224
	if (addr.ss_family == AF_UNIX)
225
		return xstrdup(((struct sockaddr_un *)&addr)->sun_path);
226
220
	if (remote) {
227
	if (remote) {
228
		addrlen = sizeof(addr);
221
		if (getpeername(sock, (struct sockaddr *)&addr, &addrlen)
229
		if (getpeername(sock, (struct sockaddr *)&addr, &addrlen)
222
		    < 0)
230
		    < 0)
223
			return NULL;
231
			return NULL;
224
	} else {
225
		if (getsockname(sock, (struct sockaddr *)&addr, &addrlen)
226
		    < 0)
227
			return NULL;
228
	}
232
	}
229
	/* Get the address in ascii. */
233
	/* Get the address in ascii. */
230
	if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop,
234
	if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop,
Lines 311-322 Link Here
311
	/* Get IP address of client. */
315
	/* Get IP address of client. */
312
	fromlen = sizeof(from);
316
	fromlen = sizeof(from);
313
	memset(&from, 0, sizeof(from));
317
	memset(&from, 0, sizeof(from));
314
	if (local) {
318
315
		if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
319
316
			error("getsockname failed: %.100s", strerror(errno));
320
	if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
317
			return 0;
321
		error("getsockname failed: %.100s", strerror(errno));
318
		}
322
		return 0;
319
	} else {
323
	}
324
325
	if (from.ss_family == AF_UNIX)
326
		return 0;
327
328
	if (!local) {
329
		fromlen = sizeof(from);
320
		if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
330
		if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
321
			debug("getpeername failed: %.100s", strerror(errno));
331
			debug("getpeername failed: %.100s", strerror(errno));
322
			return -1;
332
			return -1;
(-)channels.c (-136 / +179 lines)
Lines 2443-2602 Link Here
2443
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2443
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2444
{
2444
{
2445
	Channel *c;
2445
	Channel *c;
2446
	int sock, r, success = 0, wildcard = 0, is_client;
2446
	int sock, r, success = 0, wildcard = 0, is_client, is_unix;
2447
	struct addrinfo hints, *ai, *aitop;
2447
	struct addrinfo hints, *ai, *aitop;
2448
	const char *host, *addr;
2448
	const char *host, *path, *addr;
2449
	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2449
	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2450
	in_port_t *lport_p;
2450
	in_port_t *lport_p;
2451
	struct sockaddr_un sun;
2451
2452
2452
	host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
2453
	    listen_addr : host_to_connect;
2454
	is_client = (type == SSH_CHANNEL_PORT_LISTENER);
2453
	is_client = (type == SSH_CHANNEL_PORT_LISTENER);
2454
	is_unix = (is_client && listen_port == 0);
2455
2455
2456
	if (host == NULL) {
2456
	if (is_unix) {
2457
		error("No forward host name.");
2457
		path = listen_addr;
2458
		return 0;
2458
		if (strlen(path) >= sizeof(sun.sun_path)) {
2459
	}
2459
			error("Forward path too long.");
2460
	if (strlen(host) >= NI_MAXHOST) {
2460
			return 0;
2461
		error("Forward host name too long.");
2461
		}
2462
		return 0;
2463
	}
2464
2462
2465
	/*
2463
		memset(&sun, '\0', sizeof(sun));
2466
	 * Determine whether or not a port forward listens to loopback,
2464
		sun.sun_len = sizeof(sun);
2467
	 * specified address or wildcard. On the client, a specified bind
2465
		sun.sun_family = AF_UNIX;
2468
	 * address will always override gateway_ports. On the server, a
2466
		strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
2469
	 * gateway_ports of 1 (``yes'') will override the client's
2470
	 * specification and force a wildcard bind, whereas a value of 2
2471
	 * (``clientspecified'') will bind to whatever address the client
2472
	 * asked for.
2473
	 *
2474
	 * Special-case listen_addrs are:
2475
	 *
2476
	 * "0.0.0.0"               -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR
2477
	 * "" (empty string), "*"  -> wildcard v4/v6
2478
	 * "localhost"             -> loopback v4/v6
2479
	 */
2480
	addr = NULL;
2481
	if (listen_addr == NULL) {
2482
		/* No address specified: default to gateway_ports setting */
2483
		if (gateway_ports)
2484
			wildcard = 1;
2485
	} else if (gateway_ports || is_client) {
2486
		if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
2487
		    strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
2488
		    *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
2489
		    (!is_client && gateway_ports == 1))
2490
			wildcard = 1;
2491
		else if (strcmp(listen_addr, "localhost") != 0)
2492
			addr = listen_addr;
2493
	}
2494
2467
2495
	debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s",
2468
		if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
2496
	    type, wildcard, (addr == NULL) ? "NULL" : addr);
2469
			goto unix_error;
2497
2470
2498
	/*
2471
		if (bind(sock, (struct sockaddr *)&sun, sizeof(sun)) < 0)
2499
	 * getaddrinfo returns a loopback address if the hostname is
2472
			goto unix_error;
2500
	 * set to NULL and hints.ai_flags is not AI_PASSIVE
2473
2501
	 */
2474
		if (listen(sock, SSH_LISTEN_BACKLOG) < 0)
2502
	memset(&hints, 0, sizeof(hints));
2475
			goto unix_error;
2503
	hints.ai_family = IPv4or6;
2476
2504
	hints.ai_flags = wildcard ? AI_PASSIVE : 0;
2477
		c = channel_new("unix listener", type, sock, sock, -1,
2505
	hints.ai_socktype = SOCK_STREAM;
2478
				CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
2506
	snprintf(strport, sizeof strport, "%d", listen_port);
2479
				0, "unix listener", 1);
2507
	if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
2480
		c->path = xstrdup(host_to_connect);
2508
		if (addr == NULL) {
2481
		c->host_port = port_to_connect;
2509
			/* This really shouldn't happen */
2482
		c->listening_port = 0;
2510
			packet_disconnect("getaddrinfo: fatal error: %s",
2483
		
2511
			    ssh_gai_strerror(r));
2484
		return 1;
2512
		} else {
2485
2513
			error("channel_setup_fwd_listener: "
2486
	unix_error:
2514
			    "getaddrinfo(%.64s): %s", addr,
2487
		error("channel_setup_fwd_listener: unable to create listener "
2515
			    ssh_gai_strerror(r));
2488
		      "unix:%.200s, %s", path, strerror(errno));
2516
		}
2489
		if (sock >= 0)
2490
			close(sock);
2517
		return 0;
2491
		return 0;
2518
	}
2492
	}
2519
	if (allocated_listen_port != NULL)
2493
	else {
2520
		*allocated_listen_port = 0;
2494
		host = (is_client ? host_to_connect : listen_addr);
2521
	for (ai = aitop; ai; ai = ai->ai_next) {
2495
2522
		switch (ai->ai_family) {
2496
		if (host == NULL) {
2523
		case AF_INET:
2497
			error("No forward host name.");
2524
			lport_p = &((struct sockaddr_in *)ai->ai_addr)->
2498
			return 0;
2525
			    sin_port;
2499
		}
2526
			break;
2500
		if (strlen(host) >= NI_MAXHOST) {
2527
		case AF_INET6:
2501
			error("Forward host name too long.");
2528
			lport_p = &((struct sockaddr_in6 *)ai->ai_addr)->
2502
			return 0;
2529
			    sin6_port;
2530
			break;
2531
		default:
2532
			continue;
2533
		}
2503
		}
2504
2534
		/*
2505
		/*
2535
		 * If allocating a port for -R forwards, then use the
2506
		 * Determine whether or not a port forward listens to loopback,
2536
		 * same port for all address families.
2507
		 * specified address or wildcard. On the client, a specified bind
2508
		 * address will always override gateway_ports. On the server, a
2509
		 * gateway_ports of 1 (``yes'') will override the client's
2510
		 * specification and force a wildcard bind, whereas a value of 2
2511
		 * (``clientspecified'') will bind to whatever address the client
2512
		 * asked for.
2513
		 *
2514
		 * Special-case listen_addrs are:
2515
		 *
2516
		 * "0.0.0.0"               -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR
2517
		 * "" (empty string), "*"  -> wildcard v4/v6
2518
		 * "localhost"             -> loopback v4/v6
2537
		 */
2519
		 */
2538
		if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&
2520
		addr = NULL;
2539
		    allocated_listen_port != NULL && *allocated_listen_port > 0)
2521
		if (listen_addr == NULL) {
2540
			*lport_p = htons(*allocated_listen_port);
2522
			/* No address specified: default to gateway_ports setting */
2541
2523
			if (gateway_ports)
2542
		if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
2524
				wildcard = 1;
2543
		    strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
2525
		} else if (gateway_ports || is_client) {
2544
			error("channel_setup_fwd_listener: getnameinfo failed");
2526
			if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
2545
			continue;
2527
			     strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
2546
		}
2528
			    *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
2547
		/* Create a port to listen for the host. */
2529
			    (!is_client && gateway_ports == 1))
2548
		sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
2530
				wildcard = 1;
2549
		if (sock < 0) {
2531
			else if (strcmp(listen_addr, "localhost") != 0)
2550
			/* this is no error since kernel may not support ipv6 */
2532
				addr = listen_addr;
2551
			verbose("socket: %.100s", strerror(errno));
2552
			continue;
2553
		}
2554
2555
		channel_set_reuseaddr(sock);
2556
2557
		debug("Local forwarding listening on %s port %s.",
2558
		    ntop, strport);
2559
2560
		/* Bind the socket to the address. */
2561
		if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
2562
			/* address can be in use ipv6 address is already bound */
2563
			verbose("bind: %.100s", strerror(errno));
2564
			close(sock);
2565
			continue;
2566
		}
2567
		/* Start listening for connections on the socket. */
2568
		if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
2569
			error("listen: %.100s", strerror(errno));
2570
			close(sock);
2571
			continue;
2572
		}
2533
		}
2573
2534
2535
		debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s",
2536
		       type, wildcard, (addr == NULL) ? "NULL" : addr);
2537
2574
		/*
2538
		/*
2575
		 * listen_port == 0 requests a dynamically allocated port -
2539
		 * getaddrinfo returns a loopback address if the hostname is
2576
		 * record what we got.
2540
		 * set to NULL and hints.ai_flags is not AI_PASSIVE
2577
		 */
2541
		 */
2578
		if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&
2542
		memset(&hints, 0, sizeof(hints));
2579
		    allocated_listen_port != NULL &&
2543
		hints.ai_family = IPv4or6;
2580
		    *allocated_listen_port == 0) {
2544
		hints.ai_flags = wildcard ? AI_PASSIVE : 0;
2581
			*allocated_listen_port = get_sock_port(sock, 1);
2545
		hints.ai_socktype = SOCK_STREAM;
2582
			debug("Allocated listen port %d",
2546
		snprintf(strport, sizeof strport, "%d", listen_port);
2583
			    *allocated_listen_port);
2547
		if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
2584
		}
2548
			if (addr == NULL) {
2549
				/* This really shouldn't happen */
2550
				packet_disconnect("getaddrinfo: fatal error: %s",
2551
						  ssh_gai_strerror(r));
2552
			} else {
2553
				error("channel_setup_fwd_listener: "
2554
				      "getaddrinfo(%.64s): %s", addr,
2555
				      ssh_gai_strerror(r));
2556
			}
2557
			return 0;
2558
		}
2559
		if (allocated_listen_port != NULL)
2560
			*allocated_listen_port = 0;
2561
		for (ai = aitop; ai; ai = ai->ai_next) {
2562
			switch (ai->ai_family) {
2563
			case AF_INET:
2564
				lport_p = &((struct sockaddr_in *)ai->ai_addr)->
2565
					sin_port;
2566
				break;
2567
			case AF_INET6:
2568
				lport_p = &((struct sockaddr_in6 *)ai->ai_addr)->
2569
					sin6_port;
2570
				break;
2571
			default:
2572
				continue;
2573
			}
2574
			/*
2575
			 * If allocating a port for -R forwards, then use the
2576
			 * same port for all address families.
2577
			 */
2578
			if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&
2579
			    allocated_listen_port != NULL && *allocated_listen_port > 0)
2580
				*lport_p = htons(*allocated_listen_port);
2581
2582
			if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
2583
					strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
2584
				error("channel_setup_fwd_listener: getnameinfo failed");
2585
				continue;
2586
			}
2587
			/* Create a port to listen for the host. */
2588
			sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
2589
			if (sock < 0) {
2590
				/* this is no error since kernel may not support ipv6 */
2591
				verbose("socket: %.100s", strerror(errno));
2592
				continue;
2593
			}
2594
2595
			channel_set_reuseaddr(sock);
2596
2597
			debug("Local forwarding listening on %s port %s.",
2598
			      ntop, strport);
2599
2600
			/* Bind the socket to the address. */
2601
			if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
2602
				/* address can be in use ipv6 address is already bound */
2603
				verbose("bind: %.100s", strerror(errno));
2604
				close(sock);
2605
				continue;
2606
			} 
2607
			/* Start listening for connections on the socket. */
2608
			if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
2609
				error("listen: %.100s", strerror(errno));
2610
				close(sock);
2611
				continue;
2612
			}
2613
2614
			/*
2615
			 * listen_port == 0 requests a dynamically allocated port -
2616
			 * record what we got.
2617
			 */
2618
			if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&
2619
			    allocated_listen_port != NULL &&
2620
			    *allocated_listen_port == 0) {
2621
				*allocated_listen_port = get_sock_port(sock, 1);
2622
				debug("Allocated listen port %d",
2623
				      *allocated_listen_port);
2624
			}
2625
2626
			/* Allocate a channel number for the socket. */
2627
			c = channel_new("port listener", type, sock, sock, -1,
2628
					CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
2629
					0, "port listener", 1);
2630
			c->path = xstrdup(host);
2631
			c->host_port = port_to_connect;
2632
			c->listening_port = listen_port;
2633
			success = 1;
2634
		}
2635
2636
		if (success == 0)
2637
			error("channel_setup_fwd_listener: cannot listen to port: %d",
2638
			      listen_port);
2639
		freeaddrinfo(aitop);
2585
2640
2586
		/* Allocate a channel number for the socket. */
2641
		return success;
2587
		c = channel_new("port listener", type, sock, sock, -1,
2588
		    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
2589
		    0, "port listener", 1);
2590
		c->path = xstrdup(host);
2591
		c->host_port = port_to_connect;
2592
		c->listening_port = listen_port;
2593
		success = 1;
2594
	}
2642
	}
2595
	if (success == 0)
2596
		error("channel_setup_fwd_listener: cannot listen to port: %d",
2597
		    listen_port);
2598
	freeaddrinfo(aitop);
2599
	return success;
2600
}
2643
}
2601
2644
2602
int
2645
int
Lines 2621-2631 Link Here
2621
2664
2622
/* protocol local port fwd, used by ssh (and sshd in v1) */
2665
/* protocol local port fwd, used by ssh (and sshd in v1) */
2623
int
2666
int
2624
channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,
2667
channel_setup_local_fwd_listener(const char *listen_host_or_path, u_short listen_port,
2625
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2668
    const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2626
{
2669
{
2627
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2670
	return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2628
	    listen_host, listen_port, NULL, host_to_connect, port_to_connect,
2671
	    listen_host_or_path, listen_port, NULL, host_to_connect, port_to_connect,
2629
	    gateway_ports);
2672
	    gateway_ports);
2630
}
2673
}
2631
2674
(-)clientloop.c (-5 / +5 lines)
Lines 760-766 Link Here
760
	Forward fwd;
760
	Forward fwd;
761
761
762
	bzero(&fwd, sizeof(fwd));
762
	bzero(&fwd, sizeof(fwd));
763
	fwd.listen_host = fwd.connect_host = NULL;
763
	fwd.listen_host_or_path = fwd.connect_host = NULL;
764
764
765
	leave_raw_mode();
765
	leave_raw_mode();
766
	handler = signal(SIGINT, SIG_IGN);
766
	handler = signal(SIGINT, SIG_IGN);
Lines 845-858 Link Here
845
			goto out;
845
			goto out;
846
		}
846
		}
847
		if (local || dynamic) {
847
		if (local || dynamic) {
848
			if (channel_setup_local_fwd_listener(fwd.listen_host,
848
			if (channel_setup_local_fwd_listener(fwd.listen_host_or_path,
849
			    fwd.listen_port, fwd.connect_host,
849
			    fwd.listen_port, fwd.connect_host,
850
			    fwd.connect_port, options.gateway_ports) < 0) {
850
			    fwd.connect_port, options.gateway_ports) < 0) {
851
				logit("Port forwarding failed.");
851
				logit("Port forwarding failed.");
852
				goto out;
852
				goto out;
853
			}
853
			}
854
		} else {
854
		} else {
855
			if (channel_request_remote_forwarding(fwd.listen_host,
855
			if (channel_request_remote_forwarding(fwd.listen_host_or_path,
856
			    fwd.listen_port, fwd.connect_host,
856
			    fwd.listen_port, fwd.connect_host,
857
			    fwd.connect_port) < 0) {
857
			    fwd.connect_port) < 0) {
858
				logit("Port forwarding failed.");
858
				logit("Port forwarding failed.");
Lines 868-875 Link Here
868
	enter_raw_mode();
868
	enter_raw_mode();
869
	if (cmd)
869
	if (cmd)
870
		xfree(cmd);
870
		xfree(cmd);
871
	if (fwd.listen_host != NULL)
871
	if (fwd.listen_host_or_path != NULL)
872
		xfree(fwd.listen_host);
872
		xfree(fwd.listen_host_or_path);
873
	if (fwd.connect_host != NULL)
873
	if (fwd.connect_host != NULL)
874
		xfree(fwd.connect_host);
874
		xfree(fwd.connect_host);
875
}
875
}
(-)misc.c (-3 / +5 lines)
Lines 131-137 Link Here
131
131
132
	optlen = sizeof opt;
132
	optlen = sizeof opt;
133
	if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
133
	if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
134
		debug("getsockopt TCP_NODELAY: %.100s", strerror(errno));
134
		if (errno != ENOPROTOOPT) /* it is an UNIX domain socket */
135
			debug("getsockopt TCP_NODELAY: %.100s", strerror(errno));
135
		return;
136
		return;
136
	}
137
	}
137
	if (opt == 1) {
138
	if (opt == 1) {
Lines 375-381 Link Here
375
			return NULL;
376
			return NULL;
376
		else
377
		else
377
			s++;
378
			s++;
378
	} else if ((s = strpbrk(s, ":/")) == NULL)
379
		/* } else if ((s = strpbrk(s, ":/")) == NULL) */
380
	} else if ((s = strpbrk(s, ":")) == NULL)
379
		s = *cp + strlen(*cp); /* skip to end (see first case below) */
381
		s = *cp + strlen(*cp); /* skip to end (see first case below) */
380
382
381
	switch (*s) {
383
	switch (*s) {
Lines 384-390 Link Here
384
		break;
386
		break;
385
387
386
	case ':':
388
	case ':':
387
	case '/':
389
	  /* case '/': */
388
		*s = '\0';	/* terminate */
390
		*s = '\0';	/* terminate */
389
		*cp = s + 1;
391
		*cp = s + 1;
390
		break;
392
		break;
(-)readconf.c (-22 / +56 lines)
Lines 17-22 Link Here
17
#include <sys/socket.h>
17
#include <sys/socket.h>
18
18
19
#include <netinet/in.h>
19
#include <netinet/in.h>
20
#include <sys/un.h>
20
21
21
#include <ctype.h>
22
#include <ctype.h>
22
#include <errno.h>
23
#include <errno.h>
Lines 245-257 Link Here
245
{
246
{
246
	Forward *fwd;
247
	Forward *fwd;
247
	extern uid_t original_real_uid;
248
	extern uid_t original_real_uid;
248
	if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
249
	if (newfwd->listen_port && newfwd->listen_port < IPPORT_RESERVED &&
250
	    original_real_uid != 0)
249
		fatal("Privileged ports can only be forwarded by root.");
251
		fatal("Privileged ports can only be forwarded by root.");
250
	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
252
	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
251
		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
253
		fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
252
	fwd = &options->local_forwards[options->num_local_forwards++];
254
	fwd = &options->local_forwards[options->num_local_forwards++];
253
255
254
	fwd->listen_host = newfwd->listen_host;
256
	fwd->listen_host_or_path = newfwd->listen_host_or_path;
255
	fwd->listen_port = newfwd->listen_port;
257
	fwd->listen_port = newfwd->listen_port;
256
	fwd->connect_host = newfwd->connect_host;
258
	fwd->connect_host = newfwd->connect_host;
257
	fwd->connect_port = newfwd->connect_port;
259
	fwd->connect_port = newfwd->connect_port;
Lines 271-277 Link Here
271
		    SSH_MAX_FORWARDS_PER_DIRECTION);
273
		    SSH_MAX_FORWARDS_PER_DIRECTION);
272
	fwd = &options->remote_forwards[options->num_remote_forwards++];
274
	fwd = &options->remote_forwards[options->num_remote_forwards++];
273
275
274
	fwd->listen_host = newfwd->listen_host;
276
	fwd->listen_host_or_path = newfwd->listen_host_or_path;
275
	fwd->listen_port = newfwd->listen_port;
277
	fwd->listen_port = newfwd->listen_port;
276
	fwd->connect_host = newfwd->connect_host;
278
	fwd->connect_host = newfwd->connect_host;
277
	fwd->connect_port = newfwd->connect_port;
279
	fwd->connect_port = newfwd->connect_port;
Lines 283-296 Link Here
283
	int i;
285
	int i;
284
286
285
	for (i = 0; i < options->num_local_forwards; i++) {
287
	for (i = 0; i < options->num_local_forwards; i++) {
286
		if (options->local_forwards[i].listen_host != NULL)
288
		if (options->local_forwards[i].listen_host_or_path != NULL)
287
			xfree(options->local_forwards[i].listen_host);
289
			xfree(options->local_forwards[i].listen_host_or_path);
288
		xfree(options->local_forwards[i].connect_host);
290
		xfree(options->local_forwards[i].connect_host);
289
	}
291
	}
290
	options->num_local_forwards = 0;
292
	options->num_local_forwards = 0;
291
	for (i = 0; i < options->num_remote_forwards; i++) {
293
	for (i = 0; i < options->num_remote_forwards; i++) {
292
		if (options->remote_forwards[i].listen_host != NULL)
294
		if (options->remote_forwards[i].listen_host_or_path != NULL)
293
			xfree(options->remote_forwards[i].listen_host);
295
			xfree(options->remote_forwards[i].listen_host_or_path);
294
		xfree(options->remote_forwards[i].connect_host);
296
		xfree(options->remote_forwards[i].connect_host);
295
	}
297
	}
296
	options->num_remote_forwards = 0;
298
	options->num_remote_forwards = 0;
Lines 1206-1211 Link Here
1206
	/* options->preferred_authentications will be set in ssh */
1208
	/* options->preferred_authentications will be set in ssh */
1207
}
1209
}
1208
1210
1211
static int
1212
is_unix_domain(const char *port)
1213
{
1214
	return (strchr(port, '/') != NULL);
1215
}
1216
1209
/*
1217
/*
1210
 * parse_forward
1218
 * parse_forward
1211
 * parses a string containing a port forwarding specification of the form:
1219
 * parses a string containing a port forwarding specification of the form:
Lines 1218-1224 Link Here
1218
int
1226
int
1219
parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1227
parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1220
{
1228
{
1221
	int i;
1229
	int i, unix = 0;
1222
	char *p, *cp, *fwdarg[4];
1230
	char *p, *cp, *fwdarg[4];
1223
1231
1224
	memset(fwd, '\0', sizeof(*fwd));
1232
	memset(fwd, '\0', sizeof(*fwd));
Lines 1239-1264 Link Here
1239
1247
1240
	switch (i) {
1248
	switch (i) {
1241
	case 1:
1249
	case 1:
1242
		fwd->listen_host = NULL;
1250
		unix = is_unix_domain(fwdarg[0]);
1243
		fwd->listen_port = a2port(fwdarg[0]);
1251
		if (unix) {
1252
			fwd->listen_host_or_path = xstrdup(fwdarg[0]);
1253
			fwd->listen_port = 0;
1254
		}
1255
		else {
1256
			fwd->listen_host_or_path = NULL;
1257
			fwd->listen_port = a2port(fwdarg[0]);
1258
		}
1244
		fwd->connect_host = xstrdup("socks");
1259
		fwd->connect_host = xstrdup("socks");
1245
		break;
1260
		break;
1246
1261
1247
	case 2:
1262
	case 2:
1248
		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1263
		if (is_unix_domain(fwdarg[1]))
1264
			goto fail_free;
1265
		fwd->listen_host_or_path = xstrdup(cleanhostname(fwdarg[0]));
1249
		fwd->listen_port = a2port(fwdarg[1]);
1266
		fwd->listen_port = a2port(fwdarg[1]);
1250
		fwd->connect_host = xstrdup("socks");
1267
		fwd->connect_host = xstrdup("socks");
1251
		break;
1268
		break;
1252
1269
1253
	case 3:
1270
	case 3:
1254
		fwd->listen_host = NULL;
1271
		unix = is_unix_domain(fwdarg[0]);
1255
		fwd->listen_port = a2port(fwdarg[0]);
1272
		if (unix) {
1273
			fwd->listen_host_or_path = xstrdup(fwdarg[0]);
1274
			fwd->listen_port = 0;
1275
		}
1276
		else {
1277
			fwd->listen_host_or_path = NULL;
1278
			fwd->listen_port = a2port(fwdarg[0]);
1279
		}
1256
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1280
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1257
		fwd->connect_port = a2port(fwdarg[2]);
1281
		fwd->connect_port = a2port(fwdarg[2]);
1258
		break;
1282
		break;
1259
1283
1260
	case 4:
1284
	case 4:
1261
		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1285
		if (is_unix_domain(fwdarg[1]))
1286
			goto fail_free;
1287
		fwd->listen_host_or_path = xstrdup(cleanhostname(fwdarg[0]));
1262
		fwd->listen_port = a2port(fwdarg[1]);
1288
		fwd->listen_port = a2port(fwdarg[1]);
1263
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1289
		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1264
		fwd->connect_port = a2port(fwdarg[3]);
1290
		fwd->connect_port = a2port(fwdarg[3]);
Lines 1279-1293 Link Here
1279
			goto fail_free;
1305
			goto fail_free;
1280
	}
1306
	}
1281
1307
1282
	if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
1308
	if (fwd->listen_port < 0 || (!remotefwd && !unix && fwd->listen_port == 0))
1283
		goto fail_free;
1309
		goto fail_free;
1284
1285
	if (fwd->connect_host != NULL &&
1310
	if (fwd->connect_host != NULL &&
1286
	    strlen(fwd->connect_host) >= NI_MAXHOST)
1311
	    strlen(fwd->connect_host) >= NI_MAXHOST)
1287
		goto fail_free;
1312
		goto fail_free;
1288
	if (fwd->listen_host != NULL &&
1313
	if (unix) {
1289
	    strlen(fwd->listen_host) >= NI_MAXHOST)
1314
		if (remotefwd)
1290
		goto fail_free;
1315
			goto fail_free;
1316
		if (strlen(fwd->listen_host_or_path)
1317
		    >= sizeof(((struct sockaddr_un *)NULL)->sun_path))
1318
			goto fail_free;
1319
	}
1320
	else {
1321
		if (fwd->listen_host_or_path != NULL &&
1322
		    strlen(fwd->listen_host_or_path) >= NI_MAXHOST)
1323
			goto fail_free;
1324
	}
1291
1325
1292
1326
1293
	return (i);
1327
	return (i);
Lines 1297-1305 Link Here
1297
		xfree(fwd->connect_host);
1331
		xfree(fwd->connect_host);
1298
		fwd->connect_host = NULL;
1332
		fwd->connect_host = NULL;
1299
	}
1333
	}
1300
	if (fwd->listen_host != NULL) {
1334
	if (fwd->listen_host_or_path != NULL) {
1301
		xfree(fwd->listen_host);
1335
		xfree(fwd->listen_host_or_path);
1302
		fwd->listen_host = NULL;
1336
		fwd->listen_host_or_path = NULL;
1303
	}
1337
	}
1304
	return (0);
1338
	return (0);
1305
}
1339
}
(-)readconf.h (-2 / +2 lines)
Lines 19-26 Link Here
19
/* Data structure for representing a forwarding request. */
19
/* Data structure for representing a forwarding request. */
20
20
21
typedef struct {
21
typedef struct {
22
	char	 *listen_host;		/* Host (address) to listen on. */
22
	int	  listen_port;		/* Port to forward, 0 for UNIX domain sockets. */
23
	int	  listen_port;		/* Port to forward. */
23
	char	 *listen_host_or_path;	/* Host (address) to listen on or path for UNIX sockets */
24
	char	 *connect_host;		/* Host to connect. */
24
	char	 *connect_host;		/* Host to connect. */
25
	int	  connect_port;		/* Port to connect on connect_host. */
25
	int	  connect_port;		/* Port to connect on connect_host. */
26
}       Forward;
26
}       Forward;
(-)ssh.c (-17 / +26 lines)
Lines 855-875 Link Here
855
855
856
	/* Initiate local TCP/IP port forwardings. */
856
	/* Initiate local TCP/IP port forwardings. */
857
	for (i = 0; i < options.num_local_forwards; i++) {
857
	for (i = 0; i < options.num_local_forwards; i++) {
858
		debug("Local connections to %.200s:%d forwarded to remote "
858
		if (options.local_forwards[i].listen_port) {
859
		    "address %.200s:%d",
859
			debug("Local connections to %.200s:%d forwarded to remote "
860
		    (options.local_forwards[i].listen_host == NULL) ?
860
			      "address %.200s:%d",
861
		    (options.gateway_ports ? "*" : "LOCALHOST") :
861
			      (options.local_forwards[i].listen_host_or_path == NULL) ?
862
		    options.local_forwards[i].listen_host,
862
			      (options.gateway_ports ? "*" : "LOCALHOST") :
863
		    options.local_forwards[i].listen_port,
863
			      options.local_forwards[i].listen_host_or_path,
864
		    options.local_forwards[i].connect_host,
864
			      options.local_forwards[i].listen_port,
865
		    options.local_forwards[i].connect_port);
865
			      options.local_forwards[i].connect_host,
866
			      options.local_forwards[i].connect_port);
867
		}
868
		else {
869
			debug("Local connections to unix:%.200s forwarded to remote "
870
			      "address %.200s:%d",
871
			      options.local_forwards[i].listen_host_or_path,
872
			      options.local_forwards[i].connect_host,
873
			      options.local_forwards[i].connect_port);
874
		}
866
		success += channel_setup_local_fwd_listener(
875
		success += channel_setup_local_fwd_listener(
867
		    options.local_forwards[i].listen_host,
876
			options.local_forwards[i].listen_host_or_path,
868
		    options.local_forwards[i].listen_port,
877
			options.local_forwards[i].listen_port,
869
		    options.local_forwards[i].connect_host,
878
			options.local_forwards[i].connect_host,
870
		    options.local_forwards[i].connect_port,
879
			options.local_forwards[i].connect_port,
871
		    options.gateway_ports);
880
			options.gateway_ports);
872
	}
881
		}
873
	if (i > 0 && success != i && options.exit_on_forward_failure)
882
	if (i > 0 && success != i && options.exit_on_forward_failure)
874
		fatal("Could not request local forwarding.");
883
		fatal("Could not request local forwarding.");
875
	if (i > 0 && success == 0)
884
	if (i > 0 && success == 0)
Lines 879-891 Link Here
879
	for (i = 0; i < options.num_remote_forwards; i++) {
888
	for (i = 0; i < options.num_remote_forwards; i++) {
880
		debug("Remote connections from %.200s:%d forwarded to "
889
		debug("Remote connections from %.200s:%d forwarded to "
881
		    "local address %.200s:%d",
890
		    "local address %.200s:%d",
882
		    (options.remote_forwards[i].listen_host == NULL) ?
891
		    (options.remote_forwards[i].listen_host_or_path == NULL) ?
883
		    "LOCALHOST" : options.remote_forwards[i].listen_host,
892
		    "LOCALHOST" : options.remote_forwards[i].listen_host_or_path,
884
		    options.remote_forwards[i].listen_port,
893
		    options.remote_forwards[i].listen_port,
885
		    options.remote_forwards[i].connect_host,
894
		    options.remote_forwards[i].connect_host,
886
		    options.remote_forwards[i].connect_port);
895
		    options.remote_forwards[i].connect_port);
887
		if (channel_request_remote_forwarding(
896
		if (channel_request_remote_forwarding(
888
		    options.remote_forwards[i].listen_host,
897
		    options.remote_forwards[i].listen_host_or_path,
889
		    options.remote_forwards[i].listen_port,
898
		    options.remote_forwards[i].listen_port,
890
		    options.remote_forwards[i].connect_host,
899
		    options.remote_forwards[i].connect_host,
891
		    options.remote_forwards[i].connect_port) < 0) {
900
		    options.remote_forwards[i].connect_port) < 0) {

Return to bug 1572