[PROTOCOL auth-options.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c]
     [auth-rsa.c auth.c auth1.c auth2-hostbased.c auth2-kbdint.c auth2-none.c]
     [auth2-passwd.c auth2-pubkey.c auth2.c canohost.c channels.c channels.h]
     [clientloop.c misc.c misc.h monitor.c mux.c packet.c readconf.c]
     [readconf.h servconf.c servconf.h serverloop.c session.c ssh-agent.c]
     [ssh.c ssh_config.5 sshconnect.c sshconnect1.c sshconnect2.c sshd.c]
     [sshd_config.5 sshlogin.c]
     Add support for Unix domain socket forwarding.  A remote TCP port
     may be forwarded to a local Unix domain socket and vice versa or
     both ends may be a Unix domain socket.  This is a reimplementation
     of the streamlocal patches by William Ahern from:
         http://www.25thandclement.com/~william/projects/streamlocal.html
     OK djm@ markus@
This commit is contained in:
Damien Miller 2014-07-18 14:11:24 +10:00
parent 6262d760e0
commit 7acefbbcbe
44 changed files with 1313 additions and 450 deletions

View File

@ -1,3 +1,20 @@
20140718
- OpenBSD CVS Sync
- millert@cvs.openbsd.org 2014/07/15 15:54:14
[PROTOCOL auth-options.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c]
[auth-rsa.c auth.c auth1.c auth2-hostbased.c auth2-kbdint.c auth2-none.c]
[auth2-passwd.c auth2-pubkey.c auth2.c canohost.c channels.c channels.h]
[clientloop.c misc.c misc.h monitor.c mux.c packet.c readconf.c]
[readconf.h servconf.c servconf.h serverloop.c session.c ssh-agent.c]
[ssh.c ssh_config.5 sshconnect.c sshconnect1.c sshconnect2.c sshd.c]
[sshd_config.5 sshlogin.c]
Add support for Unix domain socket forwarding. A remote TCP port
may be forwarded to a local Unix domain socket and vice versa or
both ends may be a Unix domain socket. This is a reimplementation
of the streamlocal patches by William Ahern from:
http://www.25thandclement.com/~william/projects/streamlocal.html
OK djm@ markus@
20140717 20140717
- (djm) [digest-openssl.c] Preserve array order when disabling digests. - (djm) [digest-openssl.c] Preserve array order when disabling digests.
Reported by Petr Lautrbach. Reported by Petr Lautrbach.

View File

@ -232,6 +232,56 @@ The contents of the "data" field for layer 2 packets is:
The "frame" field contains an IEEE 802.3 Ethernet frame, including The "frame" field contains an IEEE 802.3 Ethernet frame, including
header. header.
2.4. connection: Unix domain socket forwarding
OpenSSH supports local and remote Unix domain socket forwarding
using the "streamlocal" extension. Forwarding is initiated as per
TCP sockets but with a single path instead of a host and port.
Similar to direct-tcpip, direct-streamlocal is sent by the client
to request that the server make a connection to a Unix domain socket.
byte SSH_MSG_CHANNEL_OPEN
string "direct-streamlocal@openssh.com"
uint32 sender channel
uint32 initial window size
uint32 maximum packet size
string socket path
string reserved for future use
Similar to forwarded-tcpip, forwarded-streamlocal is sent by the
server when the client has previously send the server a streamlocal-forward
GLOBAL_REQUEST.
byte SSH_MSG_CHANNEL_OPEN
string "forwarded-streamlocal@openssh.com"
uint32 sender channel
uint32 initial window size
uint32 maximum packet size
string socket path
string reserved for future use
The reserved field is not currently defined and is ignored on the
remote end. It is intended to be used in the future to pass
information about the socket file, such as ownership and mode.
The client currently sends the empty string for this field.
Similar to tcpip-forward, streamlocal-forward is sent by the client
to request remote forwarding of a Unix domain socket.
byte SSH2_MSG_GLOBAL_REQUEST
string "streamlocal-forward@openssh.com"
boolean TRUE
string socket path
Similar to cancel-tcpip-forward, cancel-streamlocal-forward is sent
by the client cancel the forwarding of a Unix domain socket.
byte SSH2_MSG_GLOBAL_REQUEST
string "cancel-streamlocal-forward@openssh.com"
boolean FALSE
string socket path
3. SFTP protocol changes 3. SFTP protocol changes
3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK 3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK
@ -356,4 +406,4 @@ respond with a SSH_FXP_STATUS message.
This extension is advertised in the SSH_FXP_VERSION hello with version This extension is advertised in the SSH_FXP_VERSION hello with version
"1". "1".
$OpenBSD: PROTOCOL,v 1.23 2013/12/01 23:19:05 djm Exp $ $OpenBSD: PROTOCOL,v 1.24 2014/07/15 15:54:14 millert Exp $

View File

@ -37,6 +37,7 @@
#include "hostfile.h" #include "hostfile.h"
#include "auth.h" #include "auth.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
/* limited protocol v1 interface to kbd-interactive authentication */ /* limited protocol v1 interface to kbd-interactive authentication */

View File

@ -40,6 +40,7 @@
#include "packet.h" #include "packet.h"
#include "log.h" #include "log.h"
#include "buffer.h" #include "buffer.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "uidswap.h" #include "uidswap.h"
#include "key.h" #include "key.h"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-options.c,v 1.63 2014/06/24 01:13:21 djm Exp $ */ /* $OpenBSD: auth-options.c,v 1.64 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -26,9 +26,9 @@
#include "log.h" #include "log.h"
#include "canohost.h" #include "canohost.h"
#include "buffer.h" #include "buffer.h"
#include "misc.h"
#include "channels.h" #include "channels.h"
#include "servconf.h" #include "servconf.h"
#include "misc.h"
#include "key.h" #include "key.h"
#include "auth-options.h" #include "auth-options.h"
#include "hostfile.h" #include "hostfile.h"
@ -325,6 +325,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
patterns[i] = '\0'; patterns[i] = '\0';
opts++; opts++;
p = patterns; p = patterns;
/* XXX - add streamlocal support */
host = hpdelim(&p); host = hpdelim(&p);
if (host == NULL || strlen(host) >= NI_MAXHOST) { if (host == NULL || strlen(host) >= NI_MAXHOST) {
debug("%.100s, line %lu: Bad permitopen " debug("%.100s, line %lu: Bad permitopen "

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-passwd.c,v 1.43 2007/09/21 08:15:29 djm Exp $ */ /* $OpenBSD: auth-passwd.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -48,6 +48,7 @@
#include "packet.h" #include "packet.h"
#include "buffer.h" #include "buffer.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "key.h" #include "key.h"
#include "hostfile.h" #include "hostfile.h"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-rh-rsa.c,v 1.43 2010/03/04 10:36:03 djm Exp $ */ /* $OpenBSD: auth-rh-rsa.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -24,6 +24,7 @@
#include "uidswap.h" #include "uidswap.h"
#include "log.h" #include "log.h"
#include "buffer.h" #include "buffer.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "key.h" #include "key.h"
#include "hostfile.h" #include "hostfile.h"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-rhosts.c,v 1.44 2010/03/07 11:57:13 dtucker Exp $ */ /* $OpenBSD: auth-rhosts.c,v 1.45 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -34,12 +34,12 @@
#include "uidswap.h" #include "uidswap.h"
#include "pathnames.h" #include "pathnames.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "canohost.h" #include "canohost.h"
#include "key.h" #include "key.h"
#include "hostfile.h" #include "hostfile.h"
#include "auth.h" #include "auth.h"
#include "misc.h"
/* import */ /* import */
extern ServerOptions options; extern ServerOptions options;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-rsa.c,v 1.87 2014/06/24 01:13:21 djm Exp $ */ /* $OpenBSD: auth-rsa.c,v 1.88 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -35,6 +35,7 @@
#include "buffer.h" #include "buffer.h"
#include "pathnames.h" #include "pathnames.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "key.h" #include "key.h"
#include "auth-options.h" #include "auth-options.h"
@ -45,7 +46,6 @@
#endif #endif
#include "monitor_wrap.h" #include "monitor_wrap.h"
#include "ssh.h" #include "ssh.h"
#include "misc.h"
#include "digest.h" #include "digest.h"

4
auth.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.c,v 1.105 2014/07/03 11:16:55 djm Exp $ */ /* $OpenBSD: auth.c,v 1.106 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* *
@ -56,6 +56,7 @@
#include "groupaccess.h" #include "groupaccess.h"
#include "log.h" #include "log.h"
#include "buffer.h" #include "buffer.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "key.h" #include "key.h"
#include "hostfile.h" #include "hostfile.h"
@ -63,7 +64,6 @@
#include "auth-options.h" #include "auth-options.h"
#include "canohost.h" #include "canohost.h"
#include "uidswap.h" #include "uidswap.h"
#include "misc.h"
#include "packet.h" #include "packet.h"
#include "loginrec.h" #include "loginrec.h"
#ifdef GSSAPI #ifdef GSSAPI

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth1.c,v 1.81 2014/07/03 11:16:55 djm Exp $ */ /* $OpenBSD: auth1.c,v 1.82 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved * All rights reserved
@ -27,6 +27,7 @@
#include "packet.h" #include "packet.h"
#include "buffer.h" #include "buffer.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "compat.h" #include "compat.h"
#include "key.h" #include "key.h"

View File

@ -41,6 +41,7 @@
#include "packet.h" #include "packet.h"
#include "dispatch.h" #include "dispatch.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
/* import */ /* import */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-hostbased.c,v 1.17 2013/12/30 23:52:27 djm Exp $ */ /* $OpenBSD: auth2-hostbased.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* *
@ -36,6 +36,7 @@
#include "packet.h" #include "packet.h"
#include "buffer.h" #include "buffer.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "compat.h" #include "compat.h"
#include "key.h" #include "key.h"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-kbdint.c,v 1.6 2013/05/17 00:13:13 djm Exp $ */ /* $OpenBSD: auth2-kbdint.c,v 1.7 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* *
@ -36,6 +36,7 @@
#include "auth.h" #include "auth.h"
#include "log.h" #include "log.h"
#include "buffer.h" #include "buffer.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
/* import */ /* import */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-none.c,v 1.17 2014/06/24 01:13:21 djm Exp $ */ /* $OpenBSD: auth2-none.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* *
@ -43,6 +43,7 @@
#include "packet.h" #include "packet.h"
#include "log.h" #include "log.h"
#include "buffer.h" #include "buffer.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "compat.h" #include "compat.h"
#include "ssh2.h" #include "ssh2.h"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-passwd.c,v 1.11 2014/02/02 03:44:31 djm Exp $ */ /* $OpenBSD: auth2-passwd.c,v 1.12 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* *
@ -41,6 +41,7 @@
#include "ssh-gss.h" #include "ssh-gss.h"
#endif #endif
#include "monitor_wrap.h" #include "monitor_wrap.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
/* import */ /* import */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-pubkey.c,v 1.40 2014/06/24 01:13:21 djm Exp $ */ /* $OpenBSD: auth2-pubkey.c,v 1.41 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* *
@ -48,6 +48,7 @@
#include "packet.h" #include "packet.h"
#include "buffer.h" #include "buffer.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "compat.h" #include "compat.h"
#include "key.h" #include "key.h"
@ -61,7 +62,6 @@
#include "ssh-gss.h" #include "ssh-gss.h"
#endif #endif
#include "monitor_wrap.h" #include "monitor_wrap.h"
#include "misc.h"
#include "authfile.h" #include "authfile.h"
#include "match.h" #include "match.h"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2.c,v 1.131 2014/07/03 11:16:55 djm Exp $ */ /* $OpenBSD: auth2.c,v 1.132 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* *
@ -41,6 +41,7 @@
#include "packet.h" #include "packet.h"
#include "log.h" #include "log.h"
#include "buffer.h" #include "buffer.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "compat.h" #include "compat.h"
#include "key.h" #include "key.h"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: canohost.c,v 1.70 2014/01/19 04:17:29 dtucker Exp $ */ /* $OpenBSD: canohost.c,v 1.71 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -16,6 +16,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
@ -262,6 +263,11 @@ get_socket_address(int sock, int remote, int flags)
if (addr.ss_family == AF_INET6) if (addr.ss_family == AF_INET6)
addrlen = sizeof(struct sockaddr_in6); addrlen = sizeof(struct sockaddr_in6);
if (addr.ss_family == AF_UNIX) {
/* Get the Unix domain socket path. */
return xstrdup(((struct sockaddr_un *)&addr)->sun_path);
}
ipv64_normalise_mapped(&addr, &addrlen); ipv64_normalise_mapped(&addr, &addrlen);
/* Get the address in ascii. */ /* Get the address in ascii. */
@ -384,6 +390,10 @@ get_sock_port(int sock, int local)
if (from.ss_family == AF_INET6) if (from.ss_family == AF_INET6)
fromlen = sizeof(struct sockaddr_in6); fromlen = sizeof(struct sockaddr_in6);
/* Unix domain sockets don't have a port number. */
if (from.ss_family == AF_UNIX)
return 0;
/* Return port number. */ /* Return port number. */
if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
strport, sizeof(strport), NI_NUMERICSERV)) != 0) strport, sizeof(strport), NI_NUMERICSERV)) != 0)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.c,v 1.335 2014/07/05 23:11:48 djm Exp $ */ /* $OpenBSD: channels.c,v 1.336 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -42,6 +42,7 @@
#include "includes.h" #include "includes.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/un.h> #include <sys/un.h>
#include <sys/socket.h> #include <sys/socket.h>
@ -107,11 +108,15 @@ static int channel_max_fd = 0;
* a corrupt remote server from accessing arbitrary TCP/IP ports on our local * a corrupt remote server from accessing arbitrary TCP/IP ports on our local
* network (which might be behind a firewall). * network (which might be behind a firewall).
*/ */
/* XXX: streamlocal wants a path instead of host:port */
/* Overload host_to_connect; we could just make this match Forward */
/* XXX - can we use listen_host instead of listen_path? */
typedef struct { typedef struct {
char *host_to_connect; /* Connect to 'host'. */ char *host_to_connect; /* Connect to 'host'. */
u_short port_to_connect; /* Connect to 'port'. */ int port_to_connect; /* Connect to 'port'. */
char *listen_host; /* Remote side should listen address. */ char *listen_host; /* Remote side should listen address. */
u_short listen_port; /* Remote side should listen port. */ char *listen_path; /* Remote side should listen path. */
int listen_port; /* Remote side should listen port. */
} ForwardPermission; } ForwardPermission;
/* List of all permitted host/port pairs to connect by the user. */ /* List of all permitted host/port pairs to connect by the user. */
@ -474,6 +479,8 @@ channel_stop_listening(void)
case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_PORT_LISTENER:
case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER:
case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
channel_close_fd(&c->sock); channel_close_fd(&c->sock);
channel_free(c); channel_free(c);
break; break;
@ -536,6 +543,8 @@ channel_still_open(void)
case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_CONNECTING:
case SSH_CHANNEL_ZOMBIE: case SSH_CHANNEL_ZOMBIE:
case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_ABANDONED:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
continue; continue;
case SSH_CHANNEL_LARVAL: case SSH_CHANNEL_LARVAL:
if (!compat20) if (!compat20)
@ -582,6 +591,8 @@ channel_find_open(void)
case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_CONNECTING:
case SSH_CHANNEL_ZOMBIE: case SSH_CHANNEL_ZOMBIE:
case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_ABANDONED:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
continue; continue;
case SSH_CHANNEL_LARVAL: case SSH_CHANNEL_LARVAL:
case SSH_CHANNEL_AUTH_SOCKET: case SSH_CHANNEL_AUTH_SOCKET:
@ -632,6 +643,8 @@ channel_open_message(void)
case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_ABANDONED:
case SSH_CHANNEL_MUX_CLIENT: case SSH_CHANNEL_MUX_CLIENT:
case SSH_CHANNEL_MUX_LISTENER: case SSH_CHANNEL_MUX_LISTENER:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
continue; continue;
case SSH_CHANNEL_LARVAL: case SSH_CHANNEL_LARVAL:
case SSH_CHANNEL_OPENING: case SSH_CHANNEL_OPENING:
@ -1387,7 +1400,6 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
static void static void
port_open_helper(Channel *c, char *rtype) port_open_helper(Channel *c, char *rtype)
{ {
int direct;
char buf[1024]; char buf[1024];
char *local_ipaddr = get_local_ipaddr(c->sock); char *local_ipaddr = get_local_ipaddr(c->sock);
int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1); int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1);
@ -1401,8 +1413,6 @@ port_open_helper(Channel *c, char *rtype)
remote_port = 65535; remote_port = 65535;
} }
direct = (strcmp(rtype, "direct-tcpip") == 0);
snprintf(buf, sizeof buf, snprintf(buf, sizeof buf,
"%s: listening port %d for %.100s port %d, " "%s: listening port %d for %.100s port %d, "
"connect from %.200s port %d to %.100s port %d", "connect from %.200s port %d to %.100s port %d",
@ -1418,18 +1428,29 @@ port_open_helper(Channel *c, char *rtype)
packet_put_int(c->self); packet_put_int(c->self);
packet_put_int(c->local_window_max); packet_put_int(c->local_window_max);
packet_put_int(c->local_maxpacket); packet_put_int(c->local_maxpacket);
if (direct) { if (strcmp(rtype, "direct-tcpip") == 0) {
/* target host, port */ /* target host, port */
packet_put_cstring(c->path); packet_put_cstring(c->path);
packet_put_int(c->host_port); packet_put_int(c->host_port);
} else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) {
/* target path */
packet_put_cstring(c->path);
} else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
/* listen path */
packet_put_cstring(c->path);
} else { } else {
/* listen address, port */ /* listen address, port */
packet_put_cstring(c->path); packet_put_cstring(c->path);
packet_put_int(local_port); packet_put_int(local_port);
} }
/* originator host and port */ if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
packet_put_cstring(remote_ipaddr); /* reserved for future owner/mode info */
packet_put_int((u_int)remote_port); packet_put_cstring("");
} else {
/* originator host and port */
packet_put_cstring(remote_ipaddr);
packet_put_int((u_int)remote_port);
}
packet_send(); packet_send();
} else { } else {
packet_start(SSH_MSG_PORT_OPEN); packet_start(SSH_MSG_PORT_OPEN);
@ -1479,14 +1500,18 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
if (c->type == SSH_CHANNEL_RPORT_LISTENER) { if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
nextstate = SSH_CHANNEL_OPENING; nextstate = SSH_CHANNEL_OPENING;
rtype = "forwarded-tcpip"; rtype = "forwarded-tcpip";
} else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) {
nextstate = SSH_CHANNEL_OPENING;
rtype = "forwarded-streamlocal@openssh.com";
} else if (c->host_port == PORT_STREAMLOCAL) {
nextstate = SSH_CHANNEL_OPENING;
rtype = "direct-streamlocal@openssh.com";
} else if (c->host_port == 0) {
nextstate = SSH_CHANNEL_DYNAMIC;
rtype = "dynamic-tcpip";
} else { } else {
if (c->host_port == 0) { nextstate = SSH_CHANNEL_OPENING;
nextstate = SSH_CHANNEL_DYNAMIC; rtype = "direct-tcpip";
rtype = "dynamic-tcpip";
} else {
nextstate = SSH_CHANNEL_OPENING;
rtype = "direct-tcpip";
}
} }
addrlen = sizeof(addr); addrlen = sizeof(addr);
@ -1499,7 +1524,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
c->notbefore = monotime() + 1; c->notbefore = monotime() + 1;
return; return;
} }
set_nodelay(newsock); if (c->host_port != PORT_STREAMLOCAL)
set_nodelay(newsock);
nc = channel_new(rtype, nextstate, newsock, newsock, -1, nc = channel_new(rtype, nextstate, newsock, newsock, -1,
c->local_window_max, c->local_maxpacket, 0, rtype, 1); c->local_window_max, c->local_maxpacket, 0, rtype, 1);
nc->listening_port = c->listening_port; nc->listening_port = c->listening_port;
@ -1988,6 +2014,8 @@ channel_handler_init_20(void)
channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
@ -1998,6 +2026,8 @@ channel_handler_init_20(void)
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener;
channel_post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener;
channel_post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener;
channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
@ -2638,7 +2668,7 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt)
originator_string = xstrdup("unknown (remote did not supply name)"); originator_string = xstrdup("unknown (remote did not supply name)");
} }
packet_check_eom(); packet_check_eom();
c = channel_connect_to(host, host_port, c = channel_connect_to_port(host, host_port,
"connected socket", originator_string); "connected socket", originator_string);
free(originator_string); free(originator_string);
free(host); free(host);
@ -2705,20 +2735,20 @@ channel_set_af(int af)
*/ */
static const char * static const char *
channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
int is_client, int gateway_ports) int is_client, struct ForwardOptions *fwd_opts)
{ {
const char *addr = NULL; const char *addr = NULL;
int wildcard = 0; int wildcard = 0;
if (listen_addr == NULL) { if (listen_addr == NULL) {
/* No address specified: default to gateway_ports setting */ /* No address specified: default to gateway_ports setting */
if (gateway_ports) if (fwd_opts->gateway_ports)
wildcard = 1; wildcard = 1;
} else if (gateway_ports || is_client) { } else if (fwd_opts->gateway_ports || is_client) {
if (((datafellows & SSH_OLD_FORWARD_ADDR) && if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) || strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
*listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
(!is_client && gateway_ports == 1)) { (!is_client && fwd_opts->gateway_ports == 1)) {
wildcard = 1; wildcard = 1;
/* /*
* Notify client if they requested a specific listen * Notify client if they requested a specific listen
@ -2752,9 +2782,8 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
} }
static int static int
channel_setup_fwd_listener(int type, const char *listen_addr, channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
u_short listen_port, int *allocated_listen_port, int *allocated_listen_port, struct ForwardOptions *fwd_opts)
const char *host_to_connect, u_short port_to_connect, int gateway_ports)
{ {
Channel *c; Channel *c;
int sock, r, success = 0, wildcard = 0, is_client; int sock, r, success = 0, wildcard = 0, is_client;
@ -2764,7 +2793,7 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
in_port_t *lport_p; in_port_t *lport_p;
host = (type == SSH_CHANNEL_RPORT_LISTENER) ? host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
listen_addr : host_to_connect; fwd->listen_host : fwd->connect_host;
is_client = (type == SSH_CHANNEL_PORT_LISTENER); is_client = (type == SSH_CHANNEL_PORT_LISTENER);
if (host == NULL) { if (host == NULL) {
@ -2777,9 +2806,9 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
} }
/* Determine the bind address, cf. channel_fwd_bind_addr() comment */ /* Determine the bind address, cf. channel_fwd_bind_addr() comment */
addr = channel_fwd_bind_addr(listen_addr, &wildcard, addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard,
is_client, gateway_ports); is_client, fwd_opts);
debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s", debug3("%s: type %d wildcard %d addr %s", __func__,
type, wildcard, (addr == NULL) ? "NULL" : addr); type, wildcard, (addr == NULL) ? "NULL" : addr);
/* /*
@ -2790,15 +2819,14 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
hints.ai_family = IPv4or6; hints.ai_family = IPv4or6;
hints.ai_flags = wildcard ? AI_PASSIVE : 0; hints.ai_flags = wildcard ? AI_PASSIVE : 0;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", listen_port); snprintf(strport, sizeof strport, "%d", fwd->listen_port);
if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
if (addr == NULL) { if (addr == NULL) {
/* This really shouldn't happen */ /* This really shouldn't happen */
packet_disconnect("getaddrinfo: fatal error: %s", packet_disconnect("getaddrinfo: fatal error: %s",
ssh_gai_strerror(r)); ssh_gai_strerror(r));
} else { } else {
error("channel_setup_fwd_listener: " error("%s: getaddrinfo(%.64s): %s", __func__, addr,
"getaddrinfo(%.64s): %s", addr,
ssh_gai_strerror(r)); ssh_gai_strerror(r));
} }
return 0; return 0;
@ -2822,13 +2850,13 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
* If allocating a port for -R forwards, then use the * If allocating a port for -R forwards, then use the
* same port for all address families. * same port for all address families.
*/ */
if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
allocated_listen_port != NULL && *allocated_listen_port > 0) allocated_listen_port != NULL && *allocated_listen_port > 0)
*lport_p = htons(*allocated_listen_port); *lport_p = htons(*allocated_listen_port);
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
error("channel_setup_fwd_listener: getnameinfo failed"); error("%s: getnameinfo failed", __func__);
continue; continue;
} }
/* Create a port to listen for the host. */ /* Create a port to listen for the host. */
@ -2865,10 +2893,10 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
} }
/* /*
* listen_port == 0 requests a dynamically allocated port - * fwd->listen_port == 0 requests a dynamically allocated port -
* record what we got. * record what we got.
*/ */
if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
allocated_listen_port != NULL && allocated_listen_port != NULL &&
*allocated_listen_port == 0) { *allocated_listen_port == 0) {
*allocated_listen_port = get_sock_port(sock, 1); *allocated_listen_port = get_sock_port(sock, 1);
@ -2881,24 +2909,98 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, "port listener", 1); 0, "port listener", 1);
c->path = xstrdup(host); c->path = xstrdup(host);
c->host_port = port_to_connect; c->host_port = fwd->connect_port;
c->listening_addr = addr == NULL ? NULL : xstrdup(addr); c->listening_addr = addr == NULL ? NULL : xstrdup(addr);
if (listen_port == 0 && allocated_listen_port != NULL && if (fwd->listen_port == 0 && allocated_listen_port != NULL &&
!(datafellows & SSH_BUG_DYNAMIC_RPORT)) !(datafellows & SSH_BUG_DYNAMIC_RPORT))
c->listening_port = *allocated_listen_port; c->listening_port = *allocated_listen_port;
else else
c->listening_port = listen_port; c->listening_port = fwd->listen_port;
success = 1; success = 1;
} }
if (success == 0) if (success == 0)
error("channel_setup_fwd_listener: cannot listen to port: %d", error("%s: cannot listen to port: %d", __func__,
listen_port); fwd->listen_port);
freeaddrinfo(aitop); freeaddrinfo(aitop);
return success; return success;
} }
int static int
channel_cancel_rport_listener(const char *host, u_short port) channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd,
struct ForwardOptions *fwd_opts)
{
struct sockaddr_un sunaddr;
const char *path;
Channel *c;
int port, sock;
mode_t omask;
switch (type) {
case SSH_CHANNEL_UNIX_LISTENER:
if (fwd->connect_path != NULL) {
if (strlen(fwd->connect_path) > sizeof(sunaddr.sun_path)) {
error("Local connecting path too long: %s",
fwd->connect_path);
return 0;
}
path = fwd->connect_path;
port = PORT_STREAMLOCAL;
} else {
if (fwd->connect_host == NULL) {
error("No forward host name.");
return 0;
}
if (strlen(fwd->connect_host) >= NI_MAXHOST) {
error("Forward host name too long.");
return 0;
}
path = fwd->connect_host;
port = fwd->connect_port;
}
break;
case SSH_CHANNEL_RUNIX_LISTENER:
path = fwd->listen_path;
port = PORT_STREAMLOCAL;
break;
default:
error("%s: unexpected channel type %d", __func__, type);
return 0;
}
if (fwd->listen_path == NULL) {
error("No forward path name.");
return 0;
}
if (strlen(fwd->listen_path) > sizeof(sunaddr.sun_path)) {
error("Local listening path too long: %s", fwd->listen_path);
return 0;
}
debug3("%s: type %d path %s", __func__, type, fwd->listen_path);
/* Start a Unix domain listener. */
omask = umask(fwd_opts->streamlocal_bind_mask);
sock = unix_listener(fwd->listen_path, SSH_LISTEN_BACKLOG,
fwd_opts->streamlocal_bind_unlink);
umask(omask);
if (sock < 0)
return 0;
debug("Local forwarding listening on path %s.", fwd->listen_path);
/* Allocate a channel number for the socket. */
c = channel_new("unix listener", type, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, "unix listener", 1);
c->path = xstrdup(path);
c->host_port = port;
c->listening_port = PORT_STREAMLOCAL;
c->listening_addr = xstrdup(fwd->listen_path);
return 1;
}
static int
channel_cancel_rport_listener_tcpip(const char *host, u_short port)
{ {
u_int i; u_int i;
int found = 0; int found = 0;
@ -2917,13 +3019,44 @@ channel_cancel_rport_listener(const char *host, u_short port)
return (found); return (found);
} }
int static int
channel_cancel_lport_listener(const char *lhost, u_short lport, channel_cancel_rport_listener_streamlocal(const char *path)
int cport, int gateway_ports)
{ {
u_int i; u_int i;
int found = 0; int found = 0;
const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, gateway_ports);
for (i = 0; i < channels_alloc; i++) {
Channel *c = channels[i];
if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER)
continue;
if (c->path == NULL)
continue;
if (strcmp(c->path, path) == 0) {
debug2("%s: close channel %d", __func__, i);
channel_free(c);
found = 1;
}
}
return (found);
}
int
channel_cancel_rport_listener(struct Forward *fwd)
{
if (fwd->listen_path != NULL)
return channel_cancel_rport_listener_streamlocal(fwd->listen_path);
else
return channel_cancel_rport_listener_tcpip(fwd->listen_host, fwd->listen_port);
}
static int
channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport,
int cport, struct ForwardOptions *fwd_opts)
{
u_int i;
int found = 0;
const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts);
for (i = 0; i < channels_alloc; i++) { for (i = 0; i < channels_alloc; i++) {
Channel *c = channels[i]; Channel *c = channels[i];
@ -2952,24 +3085,68 @@ channel_cancel_lport_listener(const char *lhost, u_short lport,
return (found); return (found);
} }
static int
channel_cancel_lport_listener_streamlocal(const char *path)
{
u_int i;
int found = 0;
if (path == NULL) {
error("%s: no path specified.", __func__);
return 0;
}
for (i = 0; i < channels_alloc; i++) {
Channel *c = channels[i];
if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER)
continue;
if (c->listening_addr == NULL)
continue;
if (strcmp(c->listening_addr, path) == 0) {
debug2("%s: close channel %d", __func__, i);
channel_free(c);
found = 1;
}
}
return (found);
}
int
channel_cancel_lport_listener(struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts)
{
if (fwd->listen_path != NULL)
return channel_cancel_lport_listener_streamlocal(fwd->listen_path);
else
return channel_cancel_lport_listener_tcpip(fwd->listen_host, fwd->listen_port, cport, fwd_opts);
}
/* protocol local port fwd, used by ssh (and sshd in v1) */ /* protocol local port fwd, used by ssh (and sshd in v1) */
int int
channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port, channel_setup_local_fwd_listener(struct Forward *fwd, struct ForwardOptions *fwd_opts)
const char *host_to_connect, u_short port_to_connect, int gateway_ports)
{ {
return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, if (fwd->listen_path != NULL) {
listen_host, listen_port, NULL, host_to_connect, port_to_connect, return channel_setup_fwd_listener_streamlocal(
gateway_ports); SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts);
} else {
return channel_setup_fwd_listener_tcpip(SSH_CHANNEL_PORT_LISTENER,
fwd, NULL, fwd_opts);
}
} }
/* protocol v2 remote port fwd, used by sshd */ /* protocol v2 remote port fwd, used by sshd */
int int
channel_setup_remote_fwd_listener(const char *listen_address, channel_setup_remote_fwd_listener(struct Forward *fwd,
u_short listen_port, int *allocated_listen_port, int gateway_ports) int *allocated_listen_port, struct ForwardOptions *fwd_opts)
{ {
return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, if (fwd->listen_path != NULL) {
listen_address, listen_port, allocated_listen_port, return channel_setup_fwd_listener_streamlocal(
NULL, 0, gateway_ports); SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts);
} else {
return channel_setup_fwd_listener_tcpip(
SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port,
fwd_opts);
}
} }
/* /*
@ -3000,27 +3177,32 @@ channel_rfwd_bind_host(const char *listen_host)
* channel_update_permitted_opens(). * channel_update_permitted_opens().
*/ */
int int
channel_request_remote_forwarding(const char *listen_host, u_short listen_port, channel_request_remote_forwarding(struct Forward *fwd)
const char *host_to_connect, u_short port_to_connect)
{ {
int type, success = 0, idx = -1; int type, success = 0, idx = -1;
/* Send the forward request to the remote side. */ /* Send the forward request to the remote side. */
if (compat20) { if (compat20) {
packet_start(SSH2_MSG_GLOBAL_REQUEST); packet_start(SSH2_MSG_GLOBAL_REQUEST);
packet_put_cstring("tcpip-forward"); if (fwd->listen_path != NULL) {
packet_put_char(1); /* boolean: want reply */ packet_put_cstring("streamlocal-forward@openssh.com");
packet_put_cstring(channel_rfwd_bind_host(listen_host)); packet_put_char(1); /* boolean: want reply */
packet_put_int(listen_port); packet_put_cstring(fwd->listen_path);
} else {
packet_put_cstring("tcpip-forward");
packet_put_char(1); /* boolean: want reply */
packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host));
packet_put_int(fwd->listen_port);
}
packet_send(); packet_send();
packet_write_wait(); packet_write_wait();
/* Assume that server accepts the request */ /* Assume that server accepts the request */
success = 1; success = 1;
} else { } else if (fwd->listen_path == NULL) {
packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
packet_put_int(listen_port); packet_put_int(fwd->listen_port);
packet_put_cstring(host_to_connect); packet_put_cstring(fwd->connect_host);
packet_put_int(port_to_connect); packet_put_int(fwd->connect_port);
packet_send(); packet_send();
packet_write_wait(); packet_write_wait();
@ -3037,24 +3219,43 @@ channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
packet_disconnect("Protocol error for port forward request:" packet_disconnect("Protocol error for port forward request:"
"received packet type %d.", type); "received packet type %d.", type);
} }
} else {
logit("Warning: Server does not support remote stream local forwarding.");
} }
if (success) { if (success) {
/* Record that connection to this host/port is permitted. */ /* Record that connection to this host/port is permitted. */
permitted_opens = xrealloc(permitted_opens, permitted_opens = xrealloc(permitted_opens,
num_permitted_opens + 1, sizeof(*permitted_opens)); num_permitted_opens + 1, sizeof(*permitted_opens));
idx = num_permitted_opens++; idx = num_permitted_opens++;
permitted_opens[idx].host_to_connect = xstrdup(host_to_connect); if (fwd->connect_path != NULL) {
permitted_opens[idx].port_to_connect = port_to_connect; permitted_opens[idx].host_to_connect =
permitted_opens[idx].listen_host = listen_host ? xstrdup(fwd->connect_path);
xstrdup(listen_host) : NULL; permitted_opens[idx].port_to_connect =
permitted_opens[idx].listen_port = listen_port; PORT_STREAMLOCAL;
} else {
permitted_opens[idx].host_to_connect =
xstrdup(fwd->connect_host);
permitted_opens[idx].port_to_connect =
fwd->connect_port;
}
if (fwd->listen_path != NULL) {
permitted_opens[idx].listen_host = NULL;
permitted_opens[idx].listen_path =
xstrdup(fwd->listen_path);
permitted_opens[idx].listen_port = PORT_STREAMLOCAL;
} else {
permitted_opens[idx].listen_host =
fwd->listen_host ? xstrdup(fwd->listen_host) : NULL;
permitted_opens[idx].listen_path = NULL;
permitted_opens[idx].listen_port = fwd->listen_port;
}
} }
return (idx); return (idx);
} }
static int static int
open_match(ForwardPermission *allowed_open, const char *requestedhost, open_match(ForwardPermission *allowed_open, const char *requestedhost,
u_short requestedport) int requestedport)
{ {
if (allowed_open->host_to_connect == NULL) if (allowed_open->host_to_connect == NULL)
return 0; return 0;
@ -3067,14 +3268,14 @@ open_match(ForwardPermission *allowed_open, const char *requestedhost,
} }
/* /*
* Note that in he listen host/port case * Note that in the listen host/port case
* we don't support FWD_PERMIT_ANY_PORT and * we don't support FWD_PERMIT_ANY_PORT and
* need to translate between the configured-host (listen_host) * need to translate between the configured-host (listen_host)
* and what we've sent to the remote server (channel_rfwd_bind_host) * and what we've sent to the remote server (channel_rfwd_bind_host)
*/ */
static int static int
open_listen_match(ForwardPermission *allowed_open, const char *requestedhost, open_listen_match_tcpip(ForwardPermission *allowed_open,
u_short requestedport, int translate) const char *requestedhost, u_short requestedport, int translate)
{ {
const char *allowed_host; const char *allowed_host;
@ -3094,12 +3295,26 @@ open_listen_match(ForwardPermission *allowed_open, const char *requestedhost,
return 1; return 1;
} }
static int
open_listen_match_streamlocal(ForwardPermission *allowed_open,
const char *requestedpath)
{
if (allowed_open->host_to_connect == NULL)
return 0;
if (allowed_open->listen_port != PORT_STREAMLOCAL)
return 0;
if (allowed_open->listen_path == NULL ||
strcmp(allowed_open->listen_path, requestedpath) != 0)
return 0;
return 1;
}
/* /*
* Request cancellation of remote forwarding of connection host:port from * Request cancellation of remote forwarding of connection host:port from
* local side. * local side.
*/ */
int static int
channel_request_rforward_cancel(const char *host, u_short port) channel_request_rforward_cancel_tcpip(const char *host, u_short port)
{ {
int i; int i;
@ -3107,7 +3322,7 @@ channel_request_rforward_cancel(const char *host, u_short port)
return -1; return -1;
for (i = 0; i < num_permitted_opens; i++) { for (i = 0; i < num_permitted_opens; i++) {
if (open_listen_match(&permitted_opens[i], host, port, 0)) if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0))
break; break;
} }
if (i >= num_permitted_opens) { if (i >= num_permitted_opens) {
@ -3121,52 +3336,104 @@ channel_request_rforward_cancel(const char *host, u_short port)
packet_put_int(port); packet_put_int(port);
packet_send(); packet_send();
permitted_opens[i].port_to_connect = 0;
permitted_opens[i].listen_port = 0; permitted_opens[i].listen_port = 0;
permitted_opens[i].port_to_connect = 0;
free(permitted_opens[i].host_to_connect); free(permitted_opens[i].host_to_connect);
permitted_opens[i].host_to_connect = NULL; permitted_opens[i].host_to_connect = NULL;
free(permitted_opens[i].listen_host); free(permitted_opens[i].listen_host);
permitted_opens[i].listen_host = NULL; permitted_opens[i].listen_host = NULL;
permitted_opens[i].listen_path = NULL;
return 0; return 0;
} }
/*
* Request cancellation of remote forwarding of Unix domain socket
* path from local side.
*/
static int
channel_request_rforward_cancel_streamlocal(const char *path)
{
int i;
if (!compat20)
return -1;
for (i = 0; i < num_permitted_opens; i++) {
if (open_listen_match_streamlocal(&permitted_opens[i], path))
break;
}
if (i >= num_permitted_opens) {
debug("%s: requested forward not found", __func__);
return -1;
}
packet_start(SSH2_MSG_GLOBAL_REQUEST);
packet_put_cstring("cancel-streamlocal-forward@openssh.com");
packet_put_char(0);
packet_put_cstring(path);
packet_send();
permitted_opens[i].listen_port = 0;
permitted_opens[i].port_to_connect = 0;
free(permitted_opens[i].host_to_connect);
permitted_opens[i].host_to_connect = NULL;
permitted_opens[i].listen_host = NULL;
free(permitted_opens[i].listen_path);
permitted_opens[i].listen_path = NULL;
return 0;
}
/*
* Request cancellation of remote forwarding of a connection from local side.
*/
int
channel_request_rforward_cancel(struct Forward *fwd)
{
if (fwd->listen_path != NULL) {
return (channel_request_rforward_cancel_streamlocal(
fwd->listen_path));
} else {
return (channel_request_rforward_cancel_tcpip(fwd->listen_host,
fwd->listen_port ? fwd->listen_port : fwd->allocated_port));
}
}
/* /*
* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
* listening for the port, and sends back a success reply (or disconnect * listening for the port, and sends back a success reply (or disconnect
* message if there was an error). * message if there was an error).
*/ */
int int
channel_input_port_forward_request(int is_root, int gateway_ports) channel_input_port_forward_request(int is_root, struct ForwardOptions *fwd_opts)
{ {
u_short port, host_port;
int success = 0; int success = 0;
char *hostname; struct Forward fwd;
/* Get arguments from the packet. */ /* Get arguments from the packet. */
port = packet_get_int(); memset(&fwd, 0, sizeof(fwd));
hostname = packet_get_string(NULL); fwd.listen_port = packet_get_int();
host_port = packet_get_int(); fwd.connect_host = packet_get_string(NULL);
fwd.connect_port = packet_get_int();
#ifndef HAVE_CYGWIN #ifndef HAVE_CYGWIN
/* /*
* Check that an unprivileged user is not trying to forward a * Check that an unprivileged user is not trying to forward a
* privileged port. * privileged port.
*/ */
if (port < IPPORT_RESERVED && !is_root) if (fwd.listen_port < IPPORT_RESERVED && !is_root)
packet_disconnect( packet_disconnect(
"Requested forwarding of port %d but user is not root.", "Requested forwarding of port %d but user is not root.",
port); fwd.listen_port);
if (host_port == 0) if (fwd.connect_port == 0)
packet_disconnect("Dynamic forwarding denied."); packet_disconnect("Dynamic forwarding denied.");
#endif #endif
/* Initiate forwarding */ /* Initiate forwarding */
success = channel_setup_local_fwd_listener(NULL, port, hostname, success = channel_setup_local_fwd_listener(&fwd, fwd_opts);
host_port, gateway_ports);
/* Free the argument string. */ /* Free the argument string. */
free(hostname); free(fwd.connect_host);
return (success ? 0 : -1); return (success ? 0 : -1);
} }
@ -3193,6 +3460,7 @@ channel_add_permitted_opens(char *host, int port)
permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);
permitted_opens[num_permitted_opens].port_to_connect = port; permitted_opens[num_permitted_opens].port_to_connect = port;
permitted_opens[num_permitted_opens].listen_host = NULL; permitted_opens[num_permitted_opens].listen_host = NULL;
permitted_opens[num_permitted_opens].listen_path = NULL;
permitted_opens[num_permitted_opens].listen_port = 0; permitted_opens[num_permitted_opens].listen_port = 0;
num_permitted_opens++; num_permitted_opens++;
@ -3227,6 +3495,8 @@ channel_update_permitted_opens(int idx, int newport)
permitted_opens[idx].host_to_connect = NULL; permitted_opens[idx].host_to_connect = NULL;
free(permitted_opens[idx].listen_host); free(permitted_opens[idx].listen_host);
permitted_opens[idx].listen_host = NULL; permitted_opens[idx].listen_host = NULL;
free(permitted_opens[idx].listen_path);
permitted_opens[idx].listen_path = NULL;
} }
} }
@ -3241,6 +3511,7 @@ channel_add_adm_permitted_opens(char *host, int port)
= xstrdup(host); = xstrdup(host);
permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port; permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port;
permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL; permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL;
permitted_adm_opens[num_adm_permitted_opens].listen_path = NULL;
permitted_adm_opens[num_adm_permitted_opens].listen_port = 0; permitted_adm_opens[num_adm_permitted_opens].listen_port = 0;
return ++num_adm_permitted_opens; return ++num_adm_permitted_opens;
} }
@ -3262,6 +3533,7 @@ channel_clear_permitted_opens(void)
for (i = 0; i < num_permitted_opens; i++) { for (i = 0; i < num_permitted_opens; i++) {
free(permitted_opens[i].host_to_connect); free(permitted_opens[i].host_to_connect);
free(permitted_opens[i].listen_host); free(permitted_opens[i].listen_host);
free(permitted_opens[i].listen_path);
} }
free(permitted_opens); free(permitted_opens);
permitted_opens = NULL; permitted_opens = NULL;
@ -3276,6 +3548,7 @@ channel_clear_adm_permitted_opens(void)
for (i = 0; i < num_adm_permitted_opens; i++) { for (i = 0; i < num_adm_permitted_opens; i++) {
free(permitted_adm_opens[i].host_to_connect); free(permitted_adm_opens[i].host_to_connect);
free(permitted_adm_opens[i].listen_host); free(permitted_adm_opens[i].listen_host);
free(permitted_adm_opens[i].listen_path);
} }
free(permitted_adm_opens); free(permitted_adm_opens);
permitted_adm_opens = NULL; permitted_adm_opens = NULL;
@ -3319,16 +3592,27 @@ static int
connect_next(struct channel_connect *cctx) connect_next(struct channel_connect *cctx)
{ {
int sock, saved_errno; int sock, saved_errno;
char ntop[NI_MAXHOST], strport[NI_MAXSERV]; struct sockaddr_un *sunaddr;
char ntop[NI_MAXHOST], strport[MAX(NI_MAXSERV,sizeof(sunaddr->sun_path))];
for (; cctx->ai; cctx->ai = cctx->ai->ai_next) { for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
if (cctx->ai->ai_family != AF_INET && switch (cctx->ai->ai_family) {
cctx->ai->ai_family != AF_INET6) case AF_UNIX:
continue; /* unix:pathname instead of host:port */
if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen, sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr;
ntop, sizeof(ntop), strport, sizeof(strport), strlcpy(ntop, "unix", sizeof(ntop));
NI_NUMERICHOST|NI_NUMERICSERV) != 0) { strlcpy(strport, sunaddr->sun_path, sizeof(strport));
error("connect_next: getnameinfo failed"); break;
case AF_INET:
case AF_INET6:
if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
ntop, sizeof(ntop), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
error("connect_next: getnameinfo failed");
continue;
}
break;
default:
continue; continue;
} }
if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype, if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
@ -3351,10 +3635,11 @@ connect_next(struct channel_connect *cctx)
errno = saved_errno; errno = saved_errno;
continue; /* fail -- try next */ continue; /* fail -- try next */
} }
if (cctx->ai->ai_family != AF_UNIX)
set_nodelay(sock);
debug("connect_next: host %.100s ([%.100s]:%s) " debug("connect_next: host %.100s ([%.100s]:%s) "
"in progress, fd=%d", cctx->host, ntop, strport, sock); "in progress, fd=%d", cctx->host, ntop, strport, sock);
cctx->ai = cctx->ai->ai_next; cctx->ai = cctx->ai->ai_next;
set_nodelay(sock);
return sock; return sock;
} }
return -1; return -1;
@ -3364,14 +3649,18 @@ static void
channel_connect_ctx_free(struct channel_connect *cctx) channel_connect_ctx_free(struct channel_connect *cctx)
{ {
free(cctx->host); free(cctx->host);
if (cctx->aitop) if (cctx->aitop) {
freeaddrinfo(cctx->aitop); if (cctx->aitop->ai_family == AF_UNIX)
free(cctx->aitop);
else
freeaddrinfo(cctx->aitop);
}
memset(cctx, 0, sizeof(*cctx)); memset(cctx, 0, sizeof(*cctx));
} }
/* Return CONNECTING channel to remote host, port */ /* Return CONNECTING channel to remote host:port or local socket path */
static Channel * static Channel *
connect_to(const char *host, u_short port, char *ctype, char *rname) connect_to(const char *name, int port, char *ctype, char *rname)
{ {
struct addrinfo hints; struct addrinfo hints;
int gaierr; int gaierr;
@ -3381,23 +3670,51 @@ connect_to(const char *host, u_short port, char *ctype, char *rname)
Channel *c; Channel *c;
memset(&cctx, 0, sizeof(cctx)); memset(&cctx, 0, sizeof(cctx));
memset(&hints, 0, sizeof(hints));
hints.ai_family = IPv4or6; if (port == PORT_STREAMLOCAL) {
hints.ai_socktype = SOCK_STREAM; struct sockaddr_un *sunaddr;
snprintf(strport, sizeof strport, "%d", port); struct addrinfo *ai;
if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) {
error("connect_to %.100s: unknown host (%s)", host, if (strlen(name) > sizeof(sunaddr->sun_path)) {
ssh_gai_strerror(gaierr)); error("%.100s: %.100s", name, strerror(ENAMETOOLONG));
return NULL; return (NULL);
}
/*
* Fake up a struct addrinfo for AF_UNIX connections.
* channel_connect_ctx_free() must check ai_family
* and use free() not freeaddirinfo() for AF_UNIX.
*/
ai = xmalloc(sizeof(*ai) + sizeof(*sunaddr));
memset(ai, 0, sizeof(*ai) + sizeof(*sunaddr));
ai->ai_addr = (struct sockaddr *)(ai + 1);
ai->ai_addrlen = sizeof(*sunaddr);
ai->ai_family = AF_UNIX;
ai->ai_socktype = SOCK_STREAM;
ai->ai_protocol = PF_UNSPEC;
sunaddr = (struct sockaddr_un *)ai->ai_addr;
sunaddr->sun_family = AF_UNIX;
strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path));
cctx.aitop = ai;
} else {
memset(&hints, 0, sizeof(hints));
hints.ai_family = IPv4or6;
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", port);
if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) != 0) {
error("connect_to %.100s: unknown host (%s)", name,
ssh_gai_strerror(gaierr));
return NULL;
}
} }
cctx.host = xstrdup(host); cctx.host = xstrdup(name);
cctx.port = port; cctx.port = port;
cctx.ai = cctx.aitop; cctx.ai = cctx.aitop;
if ((sock = connect_next(&cctx)) == -1) { if ((sock = connect_next(&cctx)) == -1) {
error("connect to %.100s port %d failed: %s", error("connect to %.100s port %d failed: %s",
host, port, strerror(errno)); name, port, strerror(errno));
channel_connect_ctx_free(&cctx); channel_connect_ctx_free(&cctx);
return NULL; return NULL;
} }
@ -3414,7 +3731,7 @@ channel_connect_by_listen_address(const char *listen_host,
int i; int i;
for (i = 0; i < num_permitted_opens; i++) { for (i = 0; i < num_permitted_opens; i++) {
if (open_listen_match(&permitted_opens[i], listen_host, if (open_listen_match_tcpip(&permitted_opens[i], listen_host,
listen_port, 1)) { listen_port, 1)) {
return connect_to( return connect_to(
permitted_opens[i].host_to_connect, permitted_opens[i].host_to_connect,
@ -3426,9 +3743,26 @@ channel_connect_by_listen_address(const char *listen_host,
return NULL; return NULL;
} }
Channel *
channel_connect_by_listen_path(const char *path, char *ctype, char *rname)
{
int i;
for (i = 0; i < num_permitted_opens; i++) {
if (open_listen_match_streamlocal(&permitted_opens[i], path)) {
return connect_to(
permitted_opens[i].host_to_connect,
permitted_opens[i].port_to_connect, ctype, rname);
}
}
error("WARNING: Server requests forwarding for unknown path %.100s",
path);
return NULL;
}
/* Check if connecting to that port is permitted and connect. */ /* Check if connecting to that port is permitted and connect. */
Channel * Channel *
channel_connect_to(const char *host, u_short port, char *ctype, char *rname) channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname)
{ {
int i, permit, permit_adm = 1; int i, permit, permit_adm = 1;
@ -3458,6 +3792,38 @@ channel_connect_to(const char *host, u_short port, char *ctype, char *rname)
return connect_to(host, port, ctype, rname); return connect_to(host, port, ctype, rname);
} }
/* Check if connecting to that path is permitted and connect. */
Channel *
channel_connect_to_path(const char *path, char *ctype, char *rname)
{
int i, permit, permit_adm = 1;
permit = all_opens_permitted;
if (!permit) {
for (i = 0; i < num_permitted_opens; i++)
if (open_match(&permitted_opens[i], path, PORT_STREAMLOCAL)) {
permit = 1;
break;
}
}
if (num_adm_permitted_opens > 0) {
permit_adm = 0;
for (i = 0; i < num_adm_permitted_opens; i++)
if (open_match(&permitted_adm_opens[i], path, PORT_STREAMLOCAL)) {
permit_adm = 1;
break;
}
}
if (!permit || !permit_adm) {
logit("Received request to connect to path %.100s, "
"but the request was denied.", path);
return NULL;
}
return connect_to(path, PORT_STREAMLOCAL, ctype, rname);
}
void void
channel_send_window_changes(void) channel_send_window_changes(void)
{ {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.h,v 1.114 2014/06/27 16:41:56 markus Exp $ */ /* $OpenBSD: channels.h,v 1.115 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -56,7 +56,9 @@
#define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */ #define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */
#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */ #define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */
#define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */ #define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */
#define SSH_CHANNEL_MAX_TYPE 18 #define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */
#define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */
#define SSH_CHANNEL_MAX_TYPE 20
#define CHANNEL_CANCEL_PORT_STATIC -1 #define CHANNEL_CANCEL_PORT_STATIC -1
@ -254,6 +256,8 @@ char *channel_open_message(void);
int channel_find_open(void); int channel_find_open(void);
/* tcp forwarding */ /* tcp forwarding */
struct Forward;
struct ForwardOptions;
void channel_set_af(int af); void channel_set_af(int af);
void channel_permit_all_opens(void); void channel_permit_all_opens(void);
void channel_add_permitted_opens(char *, int); void channel_add_permitted_opens(char *, int);
@ -263,19 +267,19 @@ void channel_update_permitted_opens(int, int);
void channel_clear_permitted_opens(void); void channel_clear_permitted_opens(void);
void channel_clear_adm_permitted_opens(void); void channel_clear_adm_permitted_opens(void);
void channel_print_adm_permitted_opens(void); void channel_print_adm_permitted_opens(void);
int channel_input_port_forward_request(int, int); int channel_input_port_forward_request(int, struct ForwardOptions *);
Channel *channel_connect_to(const char *, u_short, char *, char *); Channel *channel_connect_to_port(const char *, u_short, char *, char *);
Channel *channel_connect_to_path(const char *, char *, char *);
Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); Channel *channel_connect_stdio_fwd(const char*, u_short, int, int);
Channel *channel_connect_by_listen_address(const char *, u_short, Channel *channel_connect_by_listen_address(const char *, u_short,
char *, char *); char *, char *);
int channel_request_remote_forwarding(const char *, u_short, Channel *channel_connect_by_listen_path(const char *, char *, char *);
const char *, u_short); int channel_request_remote_forwarding(struct Forward *);
int channel_setup_local_fwd_listener(const char *, u_short, int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *);
const char *, u_short, int); int channel_request_rforward_cancel(struct Forward *);
int channel_request_rforward_cancel(const char *host, u_short port); int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *);
int channel_setup_remote_fwd_listener(const char *, u_short, int *, int); int channel_cancel_rport_listener(struct Forward *);
int channel_cancel_rport_listener(const char *, u_short); int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *);
int channel_cancel_lport_listener(const char *, u_short, int, int);
int permitopen_port(const char *); int permitopen_port(const char *);
/* x11 forwarding */ /* x11 forwarding */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.c,v 1.260 2014/06/27 16:41:56 markus Exp $ */ /* $OpenBSD: clientloop.c,v 1.261 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -100,13 +100,13 @@
#include "cipher.h" #include "cipher.h"
#include "kex.h" #include "kex.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "readconf.h" #include "readconf.h"
#include "clientloop.h" #include "clientloop.h"
#include "sshconnect.h" #include "sshconnect.h"
#include "authfd.h" #include "authfd.h"
#include "atomicio.h" #include "atomicio.h"
#include "sshpty.h" #include "sshpty.h"
#include "misc.h"
#include "match.h" #include "match.h"
#include "msg.h" #include "msg.h"
#include "roaming.h" #include "roaming.h"
@ -871,13 +871,11 @@ static void
process_cmdline(void) process_cmdline(void)
{ {
void (*handler)(int); void (*handler)(int);
char *s, *cmd, *cancel_host; char *s, *cmd;
int delete = 0, local = 0, remote = 0, dynamic = 0; int ok, delete = 0, local = 0, remote = 0, dynamic = 0;
int cancel_port, ok; struct Forward fwd;
Forward fwd;
memset(&fwd, 0, sizeof(fwd)); memset(&fwd, 0, sizeof(fwd));
fwd.listen_host = fwd.connect_host = NULL;
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
handler = signal(SIGINT, SIG_IGN); handler = signal(SIGINT, SIG_IGN);
@ -943,29 +941,20 @@ process_cmdline(void)
/* XXX update list of forwards in options */ /* XXX update list of forwards in options */
if (delete) { if (delete) {
cancel_port = 0; /* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */
cancel_host = hpdelim(&s); /* may be NULL */ if (!parse_forward(&fwd, s, 1, 0)) {
if (s != NULL) { logit("Bad forwarding close specification.");
cancel_port = a2port(s);
cancel_host = cleanhostname(cancel_host);
} else {
cancel_port = a2port(cancel_host);
cancel_host = NULL;
}
if (cancel_port <= 0) {
logit("Bad forwarding close port");
goto out; goto out;
} }
if (remote) if (remote)
ok = channel_request_rforward_cancel(cancel_host, ok = channel_request_rforward_cancel(&fwd) == 0;
cancel_port) == 0;
else if (dynamic) else if (dynamic)
ok = channel_cancel_lport_listener(cancel_host, ok = channel_cancel_lport_listener(&fwd,
cancel_port, 0, options.gateway_ports) > 0; 0, &options.fwd_opts) > 0;
else else
ok = channel_cancel_lport_listener(cancel_host, ok = channel_cancel_lport_listener(&fwd,
cancel_port, CHANNEL_CANCEL_PORT_STATIC, CHANNEL_CANCEL_PORT_STATIC,
options.gateway_ports) > 0; &options.fwd_opts) > 0;
if (!ok) { if (!ok) {
logit("Unkown port forwarding."); logit("Unkown port forwarding.");
goto out; goto out;
@ -977,16 +966,13 @@ process_cmdline(void)
goto out; goto out;
} }
if (local || dynamic) { if (local || dynamic) {
if (!channel_setup_local_fwd_listener(fwd.listen_host, if (!channel_setup_local_fwd_listener(&fwd,
fwd.listen_port, fwd.connect_host, &options.fwd_opts)) {
fwd.connect_port, options.gateway_ports)) {
logit("Port forwarding failed."); logit("Port forwarding failed.");
goto out; goto out;
} }
} else { } else {
if (channel_request_remote_forwarding(fwd.listen_host, if (channel_request_remote_forwarding(&fwd) < 0) {
fwd.listen_port, fwd.connect_host,
fwd.connect_port) < 0) {
logit("Port forwarding failed."); logit("Port forwarding failed.");
goto out; goto out;
} }
@ -999,7 +985,9 @@ out:
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
free(cmd); free(cmd);
free(fwd.listen_host); free(fwd.listen_host);
free(fwd.listen_path);
free(fwd.connect_host); free(fwd.connect_host);
free(fwd.connect_path);
} }
/* reasons to suppress output of an escape command in help output */ /* reasons to suppress output of an escape command in help output */
@ -1845,9 +1833,8 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
originator_port = packet_get_int(); originator_port = packet_get_int();
packet_check_eom(); packet_check_eom();
debug("client_request_forwarded_tcpip: listen %s port %d, " debug("%s: listen %s port %d, originator %s port %d", __func__,
"originator %s port %d", listen_address, listen_port, listen_address, listen_port, originator_address, originator_port);
originator_address, originator_port);
c = channel_connect_by_listen_address(listen_address, listen_port, c = channel_connect_by_listen_address(listen_address, listen_port,
"forwarded-tcpip", originator_address); "forwarded-tcpip", originator_address);
@ -1857,6 +1844,27 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
return c; return c;
} }
static Channel *
client_request_forwarded_streamlocal(const char *request_type, int rchan)
{
Channel *c = NULL;
char *listen_path;
/* Get the remote path. */
listen_path = packet_get_string(NULL);
/* XXX: Skip reserved field for now. */
if (packet_get_string_ptr(NULL) == NULL)
fatal("%s: packet_get_string_ptr failed", __func__);
packet_check_eom();
debug("%s: %s", __func__, listen_path);
c = channel_connect_by_listen_path(listen_path,
"forwarded-streamlocal@openssh.com", "forwarded-streamlocal");
free(listen_path);
return c;
}
static Channel * static Channel *
client_request_x11(const char *request_type, int rchan) client_request_x11(const char *request_type, int rchan)
{ {
@ -1984,6 +1992,8 @@ client_input_channel_open(int type, u_int32_t seq, void *ctxt)
if (strcmp(ctype, "forwarded-tcpip") == 0) { if (strcmp(ctype, "forwarded-tcpip") == 0) {
c = client_request_forwarded_tcpip(ctype, rchan); c = client_request_forwarded_tcpip(ctype, rchan);
} else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) {
c = client_request_forwarded_streamlocal(ctype, rchan);
} else if (strcmp(ctype, "x11") == 0) { } else if (strcmp(ctype, "x11") == 0) {
c = client_request_x11(ctype, rchan); c = client_request_x11(ctype, rchan);
} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {

49
misc.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: misc.c,v 1.93 2014/04/20 02:30:25 djm Exp $ */ /* $OpenBSD: misc.c,v 1.94 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005,2006 Damien Miller. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved.
@ -29,6 +29,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h>
#include <sys/param.h> #include <sys/param.h>
#include <stdarg.h> #include <stdarg.h>
@ -1056,6 +1057,52 @@ lowercase(char *s)
for (; *s; s++) for (; *s; s++)
*s = tolower((u_char)*s); *s = tolower((u_char)*s);
} }
int
unix_listener(const char *path, int backlog, int unlink_first)
{
struct sockaddr_un sunaddr;
int saved_errno, sock;
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) {
error("%s: \"%s\" too long for Unix domain socket", __func__,
path);
errno = ENAMETOOLONG;
return -1;
}
sock = socket(PF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
saved_errno = errno;
error("socket: %.100s", strerror(errno));
errno = saved_errno;
return -1;
}
if (unlink_first == 1) {
if (unlink(path) != 0 && errno != ENOENT)
error("unlink(%s): %.100s", path, strerror(errno));
}
if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
saved_errno = errno;
error("bind: %.100s", strerror(errno));
close(sock);
error("%s: cannot bind to path: %s", __func__, path);
errno = saved_errno;
return -1;
}
if (listen(sock, backlog) < 0) {
saved_errno = errno;
error("listen: %.100s", strerror(errno));
close(sock);
unlink(path);
error("%s: cannot listen on path: %s", __func__, path);
errno = saved_errno;
return -1;
}
return sock;
}
void void
sock_set_v6only(int s) sock_set_v6only(int s)
{ {

25
misc.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: misc.h,v 1.53 2014/05/02 03:27:54 djm Exp $ */ /* $OpenBSD: misc.h,v 1.54 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -15,6 +15,25 @@
#ifndef _MISC_H #ifndef _MISC_H
#define _MISC_H #define _MISC_H
/* Data structure for representing a forwarding request. */
struct Forward {
char *listen_host; /* Host (address) to listen on. */
int listen_port; /* Port to forward. */
char *listen_path; /* Path to bind domain socket. */
char *connect_host; /* Host to connect. */
int connect_port; /* Port to connect on connect_host. */
char *connect_path; /* Path to connect domain socket. */
int allocated_port; /* Dynamically allocated listen port */
int handle; /* Handle for dynamic listen ports */
};
/* Common server and client forwarding options. */
struct ForwardOptions {
int gateway_ports; /* Allow remote connects to forwarded ports. */
mode_t streamlocal_bind_mask; /* umask for streamlocal binds */
int streamlocal_bind_unlink; /* unlink socket before bind */
};
/* misc.c */ /* misc.c */
char *chop(char *); char *chop(char *);
@ -37,6 +56,7 @@ void ms_subtract_diff(struct timeval *, int *);
void ms_to_timeval(struct timeval *, int); void ms_to_timeval(struct timeval *, int);
time_t monotime(void); time_t monotime(void);
void lowercase(char *s); void lowercase(char *s);
int unix_listener(const char *, int, int);
void sock_set_v6only(int); void sock_set_v6only(int);
@ -68,6 +88,9 @@ int tun_open(int, int);
#define SSH_TUNID_ERR (SSH_TUNID_ANY - 1) #define SSH_TUNID_ERR (SSH_TUNID_ANY - 1)
#define SSH_TUNID_MAX (SSH_TUNID_ANY - 2) #define SSH_TUNID_MAX (SSH_TUNID_ANY - 2)
/* Fake port to indicate that host field is really a path. */
#define PORT_STREAMLOCAL -2
/* Functions to extract or store big-endian words of various sizes */ /* Functions to extract or store big-endian words of various sizes */
u_int64_t get_u64(const void *) u_int64_t get_u64(const void *)
__attribute__((__bounded__( __minbytes__, 1, 8))); __attribute__((__bounded__( __minbytes__, 1, 8)));

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.134 2014/06/24 01:13:21 djm Exp $ */ /* $OpenBSD: monitor.c,v 1.135 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org> * Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -87,6 +87,7 @@
#include "sshlogin.h" #include "sshlogin.h"
#include "canohost.h" #include "canohost.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "monitor.h" #include "monitor.h"
#include "monitor_mm.h" #include "monitor_mm.h"
@ -95,7 +96,6 @@
#endif #endif
#include "monitor_wrap.h" #include "monitor_wrap.h"
#include "monitor_fdpass.h" #include "monitor_fdpass.h"
#include "misc.h"
#include "compat.h" #include "compat.h"
#include "ssh2.h" #include "ssh2.h"
#include "roaming.h" #include "roaming.h"

203
mux.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: mux.c,v 1.45 2014/04/28 03:09:18 djm Exp $ */ /* $OpenBSD: mux.c,v 1.46 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
* *
@ -509,29 +509,33 @@ process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r)
} }
static char * static char *
format_forward(u_int ftype, Forward *fwd) format_forward(u_int ftype, struct Forward *fwd)
{ {
char *ret; char *ret;
switch (ftype) { switch (ftype) {
case MUX_FWD_LOCAL: case MUX_FWD_LOCAL:
xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d", xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d",
(fwd->listen_path != NULL) ? fwd->listen_path :
(fwd->listen_host == NULL) ? (fwd->listen_host == NULL) ?
(options.gateway_ports ? "*" : "LOCALHOST") : (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
fwd->listen_host, fwd->listen_port, fwd->listen_host, fwd->listen_port,
(fwd->connect_path != NULL) ? fwd->connect_path :
fwd->connect_host, fwd->connect_port); fwd->connect_host, fwd->connect_port);
break; break;
case MUX_FWD_DYNAMIC: case MUX_FWD_DYNAMIC:
xasprintf(&ret, "dynamic forward %.200s:%d -> *", xasprintf(&ret, "dynamic forward %.200s:%d -> *",
(fwd->listen_host == NULL) ? (fwd->listen_host == NULL) ?
(options.gateway_ports ? "*" : "LOCALHOST") : (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
fwd->listen_host, fwd->listen_port); fwd->listen_host, fwd->listen_port);
break; break;
case MUX_FWD_REMOTE: case MUX_FWD_REMOTE:
xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d", xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d",
(fwd->listen_path != NULL) ? fwd->listen_path :
(fwd->listen_host == NULL) ? (fwd->listen_host == NULL) ?
"LOCALHOST" : fwd->listen_host, "LOCALHOST" : fwd->listen_host,
fwd->listen_port, fwd->listen_port,
(fwd->connect_path != NULL) ? fwd->connect_path :
fwd->connect_host, fwd->connect_port); fwd->connect_host, fwd->connect_port);
break; break;
default: default:
@ -551,14 +555,18 @@ compare_host(const char *a, const char *b)
} }
static int static int
compare_forward(Forward *a, Forward *b) compare_forward(struct Forward *a, struct Forward *b)
{ {
if (!compare_host(a->listen_host, b->listen_host)) if (!compare_host(a->listen_host, b->listen_host))
return 0; return 0;
if (!compare_host(a->listen_path, b->listen_path))
return 0;
if (a->listen_port != b->listen_port) if (a->listen_port != b->listen_port)
return 0; return 0;
if (!compare_host(a->connect_host, b->connect_host)) if (!compare_host(a->connect_host, b->connect_host))
return 0; return 0;
if (!compare_host(a->connect_path, b->connect_path))
return 0;
if (a->connect_port != b->connect_port) if (a->connect_port != b->connect_port)
return 0; return 0;
@ -570,7 +578,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
{ {
struct mux_channel_confirm_ctx *fctx = ctxt; struct mux_channel_confirm_ctx *fctx = ctxt;
char *failmsg = NULL; char *failmsg = NULL;
Forward *rfwd; struct Forward *rfwd;
Channel *c; Channel *c;
Buffer out; Buffer out;
@ -587,7 +595,8 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
rfwd = &options.remote_forwards[fctx->fid]; rfwd = &options.remote_forwards[fctx->fid];
debug("%s: %s for: listen %d, connect %s:%d", __func__, debug("%s: %s for: listen %d, connect %s:%d", __func__,
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
rfwd->connect_host, rfwd->connect_port);
if (type == SSH2_MSG_REQUEST_SUCCESS) { if (type == SSH2_MSG_REQUEST_SUCCESS) {
if (rfwd->listen_port == 0) { if (rfwd->listen_port == 0) {
rfwd->allocated_port = packet_get_int(); rfwd->allocated_port = packet_get_int();
@ -607,8 +616,12 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
} else { } else {
if (rfwd->listen_port == 0) if (rfwd->listen_port == 0)
channel_update_permitted_opens(rfwd->handle, -1); channel_update_permitted_opens(rfwd->handle, -1);
xasprintf(&failmsg, "remote port forwarding failed for " if (rfwd->listen_path != NULL)
"listen port %d", rfwd->listen_port); xasprintf(&failmsg, "remote port forwarding failed for "
"listen path %s", rfwd->listen_path);
else
xasprintf(&failmsg, "remote port forwarding failed for "
"listen port %d", rfwd->listen_port);
} }
fail: fail:
error("%s: %s", __func__, failmsg); error("%s: %s", __func__, failmsg);
@ -627,33 +640,45 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
static int static int
process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
{ {
Forward fwd; struct Forward fwd;
char *fwd_desc = NULL; char *fwd_desc = NULL;
char *listen_addr, *connect_addr;
u_int ftype; u_int ftype;
u_int lport, cport; u_int lport, cport;
int i, ret = 0, freefwd = 1; int i, ret = 0, freefwd = 1;
fwd.listen_host = fwd.connect_host = NULL; /* XXX - lport/cport check redundant */
if (buffer_get_int_ret(&ftype, m) != 0 || if (buffer_get_int_ret(&ftype, m) != 0 ||
(fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || (listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
buffer_get_int_ret(&lport, m) != 0 || buffer_get_int_ret(&lport, m) != 0 ||
(fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || (connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
buffer_get_int_ret(&cport, m) != 0 || buffer_get_int_ret(&cport, m) != 0 ||
lport > 65535 || cport > 65535) { (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
error("%s: malformed message", __func__); error("%s: malformed message", __func__);
ret = -1; ret = -1;
goto out; goto out;
} }
if (*listen_addr == '\0') {
free(listen_addr);
listen_addr = NULL;
}
if (*connect_addr == '\0') {
free(connect_addr);
connect_addr = NULL;
}
memset(&fwd, 0, sizeof(fwd));
fwd.listen_port = lport; fwd.listen_port = lport;
if (fwd.listen_port == PORT_STREAMLOCAL)
fwd.listen_path = listen_addr;
else
fwd.listen_host = listen_addr;
fwd.connect_port = cport; fwd.connect_port = cport;
if (*fwd.listen_host == '\0') { if (fwd.connect_port == PORT_STREAMLOCAL)
free(fwd.listen_host); fwd.connect_path = connect_addr;
fwd.listen_host = NULL; else
} fwd.connect_host = connect_addr;
if (*fwd.connect_host == '\0') {
free(fwd.connect_host);
fwd.connect_host = NULL;
}
debug2("%s: channel %d: request %s", __func__, c->self, debug2("%s: channel %d: request %s", __func__, c->self,
(fwd_desc = format_forward(ftype, &fwd))); (fwd_desc = format_forward(ftype, &fwd)));
@ -662,25 +687,30 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
ftype != MUX_FWD_DYNAMIC) { ftype != MUX_FWD_DYNAMIC) {
logit("%s: invalid forwarding type %u", __func__, ftype); logit("%s: invalid forwarding type %u", __func__, ftype);
invalid: invalid:
free(fwd.listen_host); free(listen_addr);
free(fwd.connect_host); free(connect_addr);
buffer_put_int(r, MUX_S_FAILURE); buffer_put_int(r, MUX_S_FAILURE);
buffer_put_int(r, rid); buffer_put_int(r, rid);
buffer_put_cstring(r, "Invalid forwarding request"); buffer_put_cstring(r, "Invalid forwarding request");
return 0; return 0;
} }
if (fwd.listen_port >= 65536) { if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) {
logit("%s: streamlocal and dynamic forwards "
"are mutually exclusive", __func__);
goto invalid;
}
if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) {
logit("%s: invalid listen port %u", __func__, logit("%s: invalid listen port %u", __func__,
fwd.listen_port); fwd.listen_port);
goto invalid; goto invalid;
} }
if (fwd.connect_port >= 65536 || (ftype != MUX_FWD_DYNAMIC && if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536)
ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { || (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) {
logit("%s: invalid connect port %u", __func__, logit("%s: invalid connect port %u", __func__,
fwd.connect_port); fwd.connect_port);
goto invalid; goto invalid;
} }
if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL) { if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) {
logit("%s: missing connect host", __func__); logit("%s: missing connect host", __func__);
goto invalid; goto invalid;
} }
@ -731,9 +761,8 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
} }
if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
if (!channel_setup_local_fwd_listener(fwd.listen_host, if (!channel_setup_local_fwd_listener(&fwd,
fwd.listen_port, fwd.connect_host, fwd.connect_port, &options.fwd_opts)) {
options.gateway_ports)) {
fail: fail:
logit("slave-requested %s failed", fwd_desc); logit("slave-requested %s failed", fwd_desc);
buffer_put_int(r, MUX_S_FAILURE); buffer_put_int(r, MUX_S_FAILURE);
@ -746,8 +775,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
} else { } else {
struct mux_channel_confirm_ctx *fctx; struct mux_channel_confirm_ctx *fctx;
fwd.handle = channel_request_remote_forwarding(fwd.listen_host, fwd.handle = channel_request_remote_forwarding(&fwd);
fwd.listen_port, fwd.connect_host, fwd.connect_port);
if (fwd.handle < 0) if (fwd.handle < 0)
goto fail; goto fail;
add_remote_forward(&options, &fwd); add_remote_forward(&options, &fwd);
@ -768,7 +796,9 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
free(fwd_desc); free(fwd_desc);
if (freefwd) { if (freefwd) {
free(fwd.listen_host); free(fwd.listen_host);
free(fwd.listen_path);
free(fwd.connect_host); free(fwd.connect_host);
free(fwd.connect_path);
} }
return ret; return ret;
} }
@ -776,36 +806,47 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
static int static int
process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
{ {
Forward fwd, *found_fwd; struct Forward fwd, *found_fwd;
char *fwd_desc = NULL; char *fwd_desc = NULL;
const char *error_reason = NULL; const char *error_reason = NULL;
char *listen_addr = NULL, *connect_addr = NULL;
u_int ftype; u_int ftype;
int i, listen_port, ret = 0; int i, ret = 0;
u_int lport, cport; u_int lport, cport;
fwd.listen_host = fwd.connect_host = NULL;
if (buffer_get_int_ret(&ftype, m) != 0 || if (buffer_get_int_ret(&ftype, m) != 0 ||
(fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || (listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
buffer_get_int_ret(&lport, m) != 0 || buffer_get_int_ret(&lport, m) != 0 ||
(fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || (connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
buffer_get_int_ret(&cport, m) != 0 || buffer_get_int_ret(&cport, m) != 0 ||
lport > 65535 || cport > 65535) { (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
error("%s: malformed message", __func__); error("%s: malformed message", __func__);
ret = -1; ret = -1;
goto out; goto out;
} }
fwd.listen_port = lport;
fwd.connect_port = cport;
if (*fwd.listen_host == '\0') { if (*listen_addr == '\0') {
free(fwd.listen_host); free(listen_addr);
fwd.listen_host = NULL; listen_addr = NULL;
} }
if (*fwd.connect_host == '\0') { if (*connect_addr == '\0') {
free(fwd.connect_host); free(connect_addr);
fwd.connect_host = NULL; connect_addr = NULL;
} }
memset(&fwd, 0, sizeof(fwd));
fwd.listen_port = lport;
if (fwd.listen_port == PORT_STREAMLOCAL)
fwd.listen_path = listen_addr;
else
fwd.listen_host = listen_addr;
fwd.connect_port = cport;
if (fwd.connect_port == PORT_STREAMLOCAL)
fwd.connect_path = connect_addr;
else
fwd.connect_host = connect_addr;
debug2("%s: channel %d: request cancel %s", __func__, c->self, debug2("%s: channel %d: request cancel %s", __func__, c->self,
(fwd_desc = format_forward(ftype, &fwd))); (fwd_desc = format_forward(ftype, &fwd)));
@ -840,18 +881,14 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
* This shouldn't fail unless we confused the host/port * This shouldn't fail unless we confused the host/port
* between options.remote_forwards and permitted_opens. * between options.remote_forwards and permitted_opens.
* However, for dynamic allocated listen ports we need * However, for dynamic allocated listen ports we need
* to lookup the actual listen port. * to use the actual listen port.
*/ */
listen_port = (fwd.listen_port == 0) ? if (channel_request_rforward_cancel(found_fwd) == -1)
found_fwd->allocated_port : fwd.listen_port;
if (channel_request_rforward_cancel(fwd.listen_host,
listen_port) == -1)
error_reason = "port not in permitted opens"; error_reason = "port not in permitted opens";
} else { /* local and dynamic forwards */ } else { /* local and dynamic forwards */
/* Ditto */ /* Ditto */
if (channel_cancel_lport_listener(fwd.listen_host, if (channel_cancel_lport_listener(&fwd, fwd.connect_port,
fwd.listen_port, fwd.connect_port, &options.fwd_opts) == -1)
options.gateway_ports) == -1)
error_reason = "port not found"; error_reason = "port not found";
} }
@ -860,8 +897,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
buffer_put_int(r, rid); buffer_put_int(r, rid);
free(found_fwd->listen_host); free(found_fwd->listen_host);
free(found_fwd->listen_path);
free(found_fwd->connect_host); free(found_fwd->connect_host);
free(found_fwd->connect_path);
found_fwd->listen_host = found_fwd->connect_host = NULL; found_fwd->listen_host = found_fwd->connect_host = NULL;
found_fwd->listen_path = found_fwd->connect_path = NULL;
found_fwd->listen_port = found_fwd->connect_port = 0; found_fwd->listen_port = found_fwd->connect_port = 0;
} else { } else {
buffer_put_int(r, MUX_S_FAILURE); buffer_put_int(r, MUX_S_FAILURE);
@ -870,8 +910,8 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
} }
out: out:
free(fwd_desc); free(fwd_desc);
free(fwd.listen_host); free(listen_addr);
free(fwd.connect_host); free(connect_addr);
return ret; return ret;
} }
@ -1133,8 +1173,6 @@ mux_tty_alloc_failed(Channel *c)
void void
muxserver_listen(void) muxserver_listen(void)
{ {
struct sockaddr_un addr;
socklen_t sun_len;
mode_t old_umask; mode_t old_umask;
char *orig_control_path = options.control_path; char *orig_control_path = options.control_path;
char rbuf[16+1]; char rbuf[16+1];
@ -1163,23 +1201,10 @@ muxserver_listen(void)
xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf); xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf);
debug3("%s: temporary control path %s", __func__, options.control_path); debug3("%s: temporary control path %s", __func__, options.control_path);
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
sun_len = offsetof(struct sockaddr_un, sun_path) +
strlen(options.control_path) + 1;
if (strlcpy(addr.sun_path, options.control_path,
sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) {
error("ControlPath \"%s\" too long for Unix domain socket",
options.control_path);
goto disable_mux_master;
}
if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
fatal("%s socket(): %s", __func__, strerror(errno));
old_umask = umask(0177); old_umask = umask(0177);
if (bind(muxserver_sock, (struct sockaddr *)&addr, sun_len) == -1) { muxserver_sock = unix_listener(options.control_path, 64, 0);
umask(old_umask);
if (muxserver_sock < 0) {
if (errno == EINVAL || errno == EADDRINUSE) { if (errno == EINVAL || errno == EADDRINUSE) {
error("ControlSocket %s already exists, " error("ControlSocket %s already exists, "
"disabling multiplexing", options.control_path); "disabling multiplexing", options.control_path);
@ -1193,13 +1218,11 @@ muxserver_listen(void)
options.control_path = NULL; options.control_path = NULL;
options.control_master = SSHCTL_MASTER_NO; options.control_master = SSHCTL_MASTER_NO;
return; return;
} else } else {
fatal("%s bind(): %s", __func__, strerror(errno)); /* unix_listener() logs the error */
cleanup_exit(255);
}
} }
umask(old_umask);
if (listen(muxserver_sock, 64) == -1)
fatal("%s listen(): %s", __func__, strerror(errno));
/* Now atomically "move" the mux socket into position */ /* Now atomically "move" the mux socket into position */
if (link(options.control_path, orig_control_path) != 0) { if (link(options.control_path, orig_control_path) != 0) {
@ -1593,7 +1616,7 @@ mux_client_request_terminate(int fd)
} }
static int static int
mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
{ {
Buffer m; Buffer m;
char *e, *fwd_desc; char *e, *fwd_desc;
@ -1608,11 +1631,19 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd)
buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD); buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD);
buffer_put_int(&m, muxclient_request_id); buffer_put_int(&m, muxclient_request_id);
buffer_put_int(&m, ftype); buffer_put_int(&m, ftype);
buffer_put_cstring(&m, if (fwd->listen_path != NULL) {
fwd->listen_host == NULL ? "" : fwd->listen_host); buffer_put_cstring(&m, fwd->listen_path);
} else {
buffer_put_cstring(&m,
fwd->listen_host == NULL ? "" : fwd->listen_host);
}
buffer_put_int(&m, fwd->listen_port); buffer_put_int(&m, fwd->listen_port);
buffer_put_cstring(&m, if (fwd->connect_path != NULL) {
fwd->connect_host == NULL ? "" : fwd->connect_host); buffer_put_cstring(&m, fwd->connect_path);
} else {
buffer_put_cstring(&m,
fwd->connect_host == NULL ? "" : fwd->connect_host);
}
buffer_put_int(&m, fwd->connect_port); buffer_put_int(&m, fwd->connect_port);
if (mux_client_write_packet(fd, &m) != 0) if (mux_client_write_packet(fd, &m) != 0)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.c,v 1.197 2014/06/24 01:13:21 djm Exp $ */ /* $OpenBSD: packet.c,v 1.198 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -66,7 +66,6 @@
#include "crc32.h" #include "crc32.h"
#include "compress.h" #include "compress.h"
#include "deattack.h" #include "deattack.h"
#include "channels.h"
#include "compat.h" #include "compat.h"
#include "ssh1.h" #include "ssh1.h"
#include "ssh2.h" #include "ssh2.h"
@ -77,6 +76,7 @@
#include "log.h" #include "log.h"
#include "canohost.h" #include "canohost.h"
#include "misc.h" #include "misc.h"
#include "channels.h"
#include "ssh.h" #include "ssh.h"
#include "ssherr.h" #include "ssherr.h"
#include "roaming.h" #include "roaming.h"

View File

@ -1,4 +1,4 @@
/* $Id: platform.c,v 1.21 2014/01/21 01:59:29 tim Exp $ */ /* $Id: platform.c,v 1.22 2014/07/18 04:11:26 djm Exp $ */
/* /*
* Copyright (c) 2006 Darren Tucker. All rights reserved. * Copyright (c) 2006 Darren Tucker. All rights reserved.
@ -25,6 +25,7 @@
#include "log.h" #include "log.h"
#include "buffer.h" #include "buffer.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "key.h" #include "key.h"
#include "hostfile.h" #include "hostfile.h"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.c,v 1.219 2014/04/23 12:42:34 djm Exp $ */ /* $OpenBSD: readconf.c,v 1.220 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -18,6 +18,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/un.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/in_systm.h> #include <netinet/in_systm.h>
@ -48,9 +49,9 @@
#include "pathnames.h" #include "pathnames.h"
#include "log.h" #include "log.h"
#include "key.h" #include "key.h"
#include "misc.h"
#include "readconf.h" #include "readconf.h"
#include "match.h" #include "match.h"
#include "misc.h"
#include "buffer.h" #include "buffer.h"
#include "kex.h" #include "kex.h"
#include "mac.h" #include "mac.h"
@ -149,6 +150,7 @@ typedef enum {
oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
oStreamLocalBindMask, oStreamLocalBindUnlink,
oIgnoredUnknownOption, oDeprecated, oUnsupported oIgnoredUnknownOption, oDeprecated, oUnsupported
} OpCodes; } OpCodes;
@ -261,6 +263,8 @@ static struct {
{ "canonicalizehostname", oCanonicalizeHostname }, { "canonicalizehostname", oCanonicalizeHostname },
{ "canonicalizemaxdots", oCanonicalizeMaxDots }, { "canonicalizemaxdots", oCanonicalizeMaxDots },
{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
{ "streamlocalbindmask", oStreamLocalBindMask },
{ "streamlocalbindunlink", oStreamLocalBindUnlink },
{ "ignoreunknown", oIgnoreUnknown }, { "ignoreunknown", oIgnoreUnknown },
{ NULL, oBadOption } { NULL, oBadOption }
@ -272,12 +276,13 @@ static struct {
*/ */
void void
add_local_forward(Options *options, const Forward *newfwd) add_local_forward(Options *options, const struct Forward *newfwd)
{ {
Forward *fwd; struct Forward *fwd;
#ifndef NO_IPPORT_RESERVED_CONCEPT #ifndef NO_IPPORT_RESERVED_CONCEPT
extern uid_t original_real_uid; extern uid_t original_real_uid;
if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 &&
newfwd->listen_path == NULL)
fatal("Privileged ports can only be forwarded by root."); fatal("Privileged ports can only be forwarded by root.");
#endif #endif
options->local_forwards = xrealloc(options->local_forwards, options->local_forwards = xrealloc(options->local_forwards,
@ -287,8 +292,10 @@ add_local_forward(Options *options, const Forward *newfwd)
fwd->listen_host = newfwd->listen_host; fwd->listen_host = newfwd->listen_host;
fwd->listen_port = newfwd->listen_port; fwd->listen_port = newfwd->listen_port;
fwd->listen_path = newfwd->listen_path;
fwd->connect_host = newfwd->connect_host; fwd->connect_host = newfwd->connect_host;
fwd->connect_port = newfwd->connect_port; fwd->connect_port = newfwd->connect_port;
fwd->connect_path = newfwd->connect_path;
} }
/* /*
@ -297,9 +304,9 @@ add_local_forward(Options *options, const Forward *newfwd)
*/ */
void void
add_remote_forward(Options *options, const Forward *newfwd) add_remote_forward(Options *options, const struct Forward *newfwd)
{ {
Forward *fwd; struct Forward *fwd;
options->remote_forwards = xrealloc(options->remote_forwards, options->remote_forwards = xrealloc(options->remote_forwards,
options->num_remote_forwards + 1, options->num_remote_forwards + 1,
@ -308,8 +315,10 @@ add_remote_forward(Options *options, const Forward *newfwd)
fwd->listen_host = newfwd->listen_host; fwd->listen_host = newfwd->listen_host;
fwd->listen_port = newfwd->listen_port; fwd->listen_port = newfwd->listen_port;
fwd->listen_path = newfwd->listen_path;
fwd->connect_host = newfwd->connect_host; fwd->connect_host = newfwd->connect_host;
fwd->connect_port = newfwd->connect_port; fwd->connect_port = newfwd->connect_port;
fwd->connect_path = newfwd->connect_path;
fwd->handle = newfwd->handle; fwd->handle = newfwd->handle;
fwd->allocated_port = 0; fwd->allocated_port = 0;
} }
@ -321,7 +330,9 @@ clear_forwardings(Options *options)
for (i = 0; i < options->num_local_forwards; i++) { for (i = 0; i < options->num_local_forwards; i++) {
free(options->local_forwards[i].listen_host); free(options->local_forwards[i].listen_host);
free(options->local_forwards[i].listen_path);
free(options->local_forwards[i].connect_host); free(options->local_forwards[i].connect_host);
free(options->local_forwards[i].connect_path);
} }
if (options->num_local_forwards > 0) { if (options->num_local_forwards > 0) {
free(options->local_forwards); free(options->local_forwards);
@ -330,7 +341,9 @@ clear_forwardings(Options *options)
options->num_local_forwards = 0; options->num_local_forwards = 0;
for (i = 0; i < options->num_remote_forwards; i++) { for (i = 0; i < options->num_remote_forwards; i++) {
free(options->remote_forwards[i].listen_host); free(options->remote_forwards[i].listen_host);
free(options->remote_forwards[i].listen_path);
free(options->remote_forwards[i].connect_host); free(options->remote_forwards[i].connect_host);
free(options->remote_forwards[i].connect_path);
} }
if (options->num_remote_forwards > 0) { if (options->num_remote_forwards > 0) {
free(options->remote_forwards); free(options->remote_forwards);
@ -715,7 +728,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host,
LogLevel *log_level_ptr; LogLevel *log_level_ptr;
long long val64; long long val64;
size_t len; size_t len;
Forward fwd; struct Forward fwd;
const struct multistate *multistate_ptr; const struct multistate *multistate_ptr;
struct allowed_cname *cname; struct allowed_cname *cname;
@ -805,7 +818,7 @@ parse_time:
goto parse_time; goto parse_time;
case oGatewayPorts: case oGatewayPorts:
intptr = &options->gateway_ports; intptr = &options->fwd_opts.gateway_ports;
goto parse_flag; goto parse_flag;
case oExitOnForwardFailure: case oExitOnForwardFailure:
@ -1405,6 +1418,21 @@ parse_int:
intptr = &options->canonicalize_fallback_local; intptr = &options->canonicalize_fallback_local;
goto parse_flag; goto parse_flag;
case oStreamLocalBindMask:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
/* Parse mode in octal format */
value = strtol(arg, &endofnumber, 8);
if (arg == endofnumber || value < 0 || value > 0777)
fatal("%.200s line %d: Bad mask.", filename, linenum);
options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
break;
case oStreamLocalBindUnlink:
intptr = &options->fwd_opts.streamlocal_bind_unlink;
goto parse_flag;
case oDeprecated: case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"", debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword); filename, linenum, keyword);
@ -1502,7 +1530,9 @@ initialize_options(Options * options)
options->forward_x11_timeout = -1; options->forward_x11_timeout = -1;
options->exit_on_forward_failure = -1; options->exit_on_forward_failure = -1;
options->xauth_location = NULL; options->xauth_location = NULL;
options->gateway_ports = -1; options->fwd_opts.gateway_ports = -1;
options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
options->fwd_opts.streamlocal_bind_unlink = -1;
options->use_privileged_port = -1; options->use_privileged_port = -1;
options->rsa_authentication = -1; options->rsa_authentication = -1;
options->pubkey_authentication = -1; options->pubkey_authentication = -1;
@ -1615,8 +1645,12 @@ fill_default_options(Options * options)
options->exit_on_forward_failure = 0; options->exit_on_forward_failure = 0;
if (options->xauth_location == NULL) if (options->xauth_location == NULL)
options->xauth_location = _PATH_XAUTH; options->xauth_location = _PATH_XAUTH;
if (options->gateway_ports == -1) if (options->fwd_opts.gateway_ports == -1)
options->gateway_ports = 0; options->fwd_opts.gateway_ports = 0;
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
options->fwd_opts.streamlocal_bind_mask = 0177;
if (options->fwd_opts.streamlocal_bind_unlink == -1)
options->fwd_opts.streamlocal_bind_unlink = 0;
if (options->use_privileged_port == -1) if (options->use_privileged_port == -1)
options->use_privileged_port = 0; options->use_privileged_port = 0;
if (options->rsa_authentication == -1) if (options->rsa_authentication == -1)
@ -1768,22 +1802,92 @@ fill_default_options(Options * options)
/* options->preferred_authentications will be set in ssh */ /* options->preferred_authentications will be set in ssh */
} }
struct fwdarg {
char *arg;
int ispath;
};
/*
* parse_fwd_field
* parses the next field in a port forwarding specification.
* sets fwd to the parsed field and advances p past the colon
* or sets it to NULL at end of string.
* returns 0 on success, else non-zero.
*/
static int
parse_fwd_field(char **p, struct fwdarg *fwd)
{
char *ep, *cp = *p;
int ispath = 0;
if (*cp == '\0') {
*p = NULL;
return -1; /* end of string */
}
/*
* A field escaped with square brackets is used literally.
* XXX - allow ']' to be escaped via backslash?
*/
if (*cp == '[') {
/* find matching ']' */
for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
if (*ep == '/')
ispath = 1;
}
/* no matching ']' or not at end of field. */
if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
return -1;
/* NUL terminate the field and advance p past the colon */
*ep++ = '\0';
if (*ep != '\0')
*ep++ = '\0';
fwd->arg = cp + 1;
fwd->ispath = ispath;
*p = ep;
return 0;
}
for (cp = *p; *cp != '\0'; cp++) {
switch (*cp) {
case '\\':
memmove(cp, cp + 1, strlen(cp + 1) + 1);
cp++;
break;
case '/':
ispath = 1;
break;
case ':':
*cp++ = '\0';
goto done;
}
}
done:
fwd->arg = *p;
fwd->ispath = ispath;
*p = cp;
return 0;
}
/* /*
* parse_forward * parse_forward
* parses a string containing a port forwarding specification of the form: * parses a string containing a port forwarding specification of the form:
* dynamicfwd == 0 * dynamicfwd == 0
* [listenhost:]listenport:connecthost:connectport * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
* listenpath:connectpath
* dynamicfwd == 1 * dynamicfwd == 1
* [listenhost:]listenport * [listenhost:]listenport
* returns number of arguments parsed or zero on error * returns number of arguments parsed or zero on error
*/ */
int int
parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
{ {
struct fwdarg fwdargs[4];
char *p, *cp;
int i; int i;
char *p, *cp, *fwdarg[4];
memset(fwd, '\0', sizeof(*fwd)); memset(fwd, 0, sizeof(*fwd));
memset(fwdargs, 0, sizeof(fwdargs));
cp = p = xstrdup(fwdspec); cp = p = xstrdup(fwdspec);
@ -1791,39 +1895,70 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
while (isspace((u_char)*cp)) while (isspace((u_char)*cp))
cp++; cp++;
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i) {
if ((fwdarg[i] = hpdelim(&cp)) == NULL) if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
break; break;
}
/* Check for trailing garbage */ /* Check for trailing garbage */
if (cp != NULL) if (cp != NULL && *cp != '\0') {
i = 0; /* failure */ i = 0; /* failure */
}
switch (i) { switch (i) {
case 1: case 1:
fwd->listen_host = NULL; if (fwdargs[0].ispath) {
fwd->listen_port = a2port(fwdarg[0]); fwd->listen_path = xstrdup(fwdargs[0].arg);
fwd->listen_port = PORT_STREAMLOCAL;
} else {
fwd->listen_host = NULL;
fwd->listen_port = a2port(fwdargs[0].arg);
}
fwd->connect_host = xstrdup("socks"); fwd->connect_host = xstrdup("socks");
break; break;
case 2: case 2:
fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); if (fwdargs[0].ispath && fwdargs[1].ispath) {
fwd->listen_port = a2port(fwdarg[1]); fwd->listen_path = xstrdup(fwdargs[0].arg);
fwd->connect_host = xstrdup("socks"); fwd->listen_port = PORT_STREAMLOCAL;
fwd->connect_path = xstrdup(fwdargs[1].arg);
fwd->connect_port = PORT_STREAMLOCAL;
} else if (fwdargs[1].ispath) {
fwd->listen_host = NULL;
fwd->listen_port = a2port(fwdargs[0].arg);
fwd->connect_path = xstrdup(fwdargs[1].arg);
fwd->connect_port = PORT_STREAMLOCAL;
} else {
fwd->listen_host = xstrdup(fwdargs[0].arg);
fwd->listen_port = a2port(fwdargs[1].arg);
fwd->connect_host = xstrdup("socks");
}
break; break;
case 3: case 3:
fwd->listen_host = NULL; if (fwdargs[0].ispath) {
fwd->listen_port = a2port(fwdarg[0]); fwd->listen_path = xstrdup(fwdargs[0].arg);
fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); fwd->listen_port = PORT_STREAMLOCAL;
fwd->connect_port = a2port(fwdarg[2]); fwd->connect_host = xstrdup(fwdargs[1].arg);
fwd->connect_port = a2port(fwdargs[2].arg);
} else if (fwdargs[2].ispath) {
fwd->listen_host = xstrdup(fwdargs[0].arg);
fwd->listen_port = a2port(fwdargs[1].arg);
fwd->connect_path = xstrdup(fwdargs[2].arg);
fwd->connect_port = PORT_STREAMLOCAL;
} else {
fwd->listen_host = NULL;
fwd->listen_port = a2port(fwdargs[0].arg);
fwd->connect_host = xstrdup(fwdargs[1].arg);
fwd->connect_port = a2port(fwdargs[2].arg);
}
break; break;
case 4: case 4:
fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); fwd->listen_host = xstrdup(fwdargs[0].arg);
fwd->listen_port = a2port(fwdarg[1]); fwd->listen_port = a2port(fwdargs[1].arg);
fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); fwd->connect_host = xstrdup(fwdargs[2].arg);
fwd->connect_port = a2port(fwdarg[3]); fwd->connect_port = a2port(fwdargs[3].arg);
break; break;
default: default:
i = 0; /* failure */ i = 0; /* failure */
@ -1835,29 +1970,42 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
if (!(i == 1 || i == 2)) if (!(i == 1 || i == 2))
goto fail_free; goto fail_free;
} else { } else {
if (!(i == 3 || i == 4)) if (!(i == 3 || i == 4)) {
goto fail_free; if (fwd->connect_path == NULL &&
if (fwd->connect_port <= 0) fwd->listen_path == NULL)
goto fail_free;
}
if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
goto fail_free; goto fail_free;
} }
if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
(!remotefwd && fwd->listen_port == 0))
goto fail_free; goto fail_free;
if (fwd->connect_host != NULL && if (fwd->connect_host != NULL &&
strlen(fwd->connect_host) >= NI_MAXHOST) strlen(fwd->connect_host) >= NI_MAXHOST)
goto fail_free; goto fail_free;
/* XXX - if connecting to a remote socket, max sun len may not match this host */
if (fwd->connect_path != NULL &&
strlen(fwd->connect_path) >= PATH_MAX_SUN)
goto fail_free;
if (fwd->listen_host != NULL && if (fwd->listen_host != NULL &&
strlen(fwd->listen_host) >= NI_MAXHOST) strlen(fwd->listen_host) >= NI_MAXHOST)
goto fail_free; goto fail_free;
if (fwd->listen_path != NULL &&
strlen(fwd->listen_path) >= PATH_MAX_SUN)
goto fail_free;
return (i); return (i);
fail_free: fail_free:
free(fwd->connect_host); free(fwd->connect_host);
fwd->connect_host = NULL; fwd->connect_host = NULL;
free(fwd->connect_path);
fwd->connect_path = NULL;
free(fwd->listen_host); free(fwd->listen_host);
fwd->listen_host = NULL; fwd->listen_host = NULL;
free(fwd->listen_path);
fwd->listen_path = NULL;
return (0); return (0);
} }

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.h,v 1.101 2014/02/23 20:11:36 djm Exp $ */ /* $OpenBSD: readconf.h,v 1.102 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -16,21 +16,12 @@
#ifndef READCONF_H #ifndef READCONF_H
#define READCONF_H #define READCONF_H
/* Data structure for representing a forwarding request. */
typedef struct {
char *listen_host; /* Host (address) to listen on. */
int listen_port; /* Port to forward. */
char *connect_host; /* Host to connect. */
int connect_port; /* Port to connect on connect_host. */
int allocated_port; /* Dynamically allocated listen port */
int handle; /* Handle for dynamic listen ports */
} Forward;
/* Data structure for representing option data. */ /* Data structure for representing option data. */
#define MAX_SEND_ENV 256 #define MAX_SEND_ENV 256
#define SSH_MAX_HOSTS_FILES 32 #define SSH_MAX_HOSTS_FILES 32
#define MAX_CANON_DOMAINS 32 #define MAX_CANON_DOMAINS 32
#define PATH_MAX_SUN (sizeof((struct sockaddr_un *)0)->sun_path)
struct allowed_cname { struct allowed_cname {
char *source_list; char *source_list;
@ -44,7 +35,7 @@ typedef struct {
int forward_x11_trusted; /* Trust Forward X11 display. */ int forward_x11_trusted; /* Trust Forward X11 display. */
int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */ int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */
char *xauth_location; /* Location for xauth program */ char *xauth_location; /* Location for xauth program */
int gateway_ports; /* Allow remote connects to forwarded ports. */ struct ForwardOptions fwd_opts; /* forwarding options */
int use_privileged_port; /* Don't use privileged port if false. */ int use_privileged_port; /* Don't use privileged port if false. */
int rhosts_rsa_authentication; /* Try rhosts with RSA int rhosts_rsa_authentication; /* Try rhosts with RSA
* authentication. */ * authentication. */
@ -106,11 +97,11 @@ typedef struct {
/* Local TCP/IP forward requests. */ /* Local TCP/IP forward requests. */
int num_local_forwards; int num_local_forwards;
Forward *local_forwards; struct Forward *local_forwards;
/* Remote TCP/IP forward requests. */ /* Remote TCP/IP forward requests. */
int num_remote_forwards; int num_remote_forwards;
Forward *remote_forwards; struct Forward *remote_forwards;
int clear_forwardings; int clear_forwardings;
int enable_ssh_keysign; int enable_ssh_keysign;
@ -181,12 +172,12 @@ int process_config_line(Options *, struct passwd *, const char *, char *,
const char *, int, int *, int); const char *, int, int *, int);
int read_config_file(const char *, struct passwd *, const char *, int read_config_file(const char *, struct passwd *, const char *,
Options *, int); Options *, int);
int parse_forward(Forward *, const char *, int, int); int parse_forward(struct Forward *, const char *, int, int);
int default_ssh_port(void); int default_ssh_port(void);
int option_clear_or_none(const char *); int option_clear_or_none(const char *);
void add_local_forward(Options *, const Forward *); void add_local_forward(Options *, const struct Forward *);
void add_remote_forward(Options *, const Forward *); void add_remote_forward(Options *, const struct Forward *);
void add_identity_file(Options *, const char *, const char *, int); void add_identity_file(Options *, const char *, const char *, int);
#endif /* READCONF_H */ #endif /* READCONF_H */

View File

@ -60,7 +60,7 @@ static const struct sandbox_policy preauth_policy[] = {
{ SYS___sysctl, SYSTR_POLICY_PERMIT }, { SYS___sysctl, SYSTR_POLICY_PERMIT },
#endif #endif
{ SYS_sendsyslog, SYSTR_POLICY_PERMIT }, // { SYS_sendsyslog, SYSTR_POLICY_PERMIT },
{ SYS_close, SYSTR_POLICY_PERMIT }, { SYS_close, SYSTR_POLICY_PERMIT },
{ SYS_exit, SYSTR_POLICY_PERMIT }, { SYS_exit, SYSTR_POLICY_PERMIT },
{ SYS_getpid, SYSTR_POLICY_PERMIT }, { SYS_getpid, SYSTR_POLICY_PERMIT },

View File

@ -1,5 +1,5 @@
/* $OpenBSD: servconf.c,v 1.250 2014/07/03 22:40:43 djm Exp $ */ /* $OpenBSD: servconf.c,v 1.251 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved * All rights reserved
@ -39,10 +39,10 @@
#include "ssh.h" #include "ssh.h"
#include "log.h" #include "log.h"
#include "buffer.h" #include "buffer.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "compat.h" #include "compat.h"
#include "pathnames.h" #include "pathnames.h"
#include "misc.h"
#include "cipher.h" #include "cipher.h"
#include "key.h" #include "key.h"
#include "kex.h" #include "kex.h"
@ -120,6 +120,7 @@ initialize_server_options(ServerOptions *options)
options->rekey_limit = -1; options->rekey_limit = -1;
options->rekey_interval = -1; options->rekey_interval = -1;
options->allow_tcp_forwarding = -1; options->allow_tcp_forwarding = -1;
options->allow_streamlocal_forwarding = -1;
options->allow_agent_forwarding = -1; options->allow_agent_forwarding = -1;
options->num_allow_users = 0; options->num_allow_users = 0;
options->num_deny_users = 0; options->num_deny_users = 0;
@ -129,7 +130,9 @@ initialize_server_options(ServerOptions *options)
options->macs = NULL; options->macs = NULL;
options->kex_algorithms = NULL; options->kex_algorithms = NULL;
options->protocol = SSH_PROTO_UNKNOWN; options->protocol = SSH_PROTO_UNKNOWN;
options->gateway_ports = -1; options->fwd_opts.gateway_ports = -1;
options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
options->fwd_opts.streamlocal_bind_unlink = -1;
options->num_subsystems = 0; options->num_subsystems = 0;
options->max_startups_begin = -1; options->max_startups_begin = -1;
options->max_startups_rate = -1; options->max_startups_rate = -1;
@ -269,10 +272,12 @@ fill_default_server_options(ServerOptions *options)
options->rekey_interval = 0; options->rekey_interval = 0;
if (options->allow_tcp_forwarding == -1) if (options->allow_tcp_forwarding == -1)
options->allow_tcp_forwarding = FORWARD_ALLOW; options->allow_tcp_forwarding = FORWARD_ALLOW;
if (options->allow_streamlocal_forwarding == -1)
options->allow_streamlocal_forwarding = FORWARD_ALLOW;
if (options->allow_agent_forwarding == -1) if (options->allow_agent_forwarding == -1)
options->allow_agent_forwarding = 1; options->allow_agent_forwarding = 1;
if (options->gateway_ports == -1) if (options->fwd_opts.gateway_ports == -1)
options->gateway_ports = 0; options->fwd_opts.gateway_ports = 0;
if (options->max_startups == -1) if (options->max_startups == -1)
options->max_startups = 100; options->max_startups = 100;
if (options->max_startups_rate == -1) if (options->max_startups_rate == -1)
@ -303,6 +308,10 @@ fill_default_server_options(ServerOptions *options)
options->ip_qos_bulk = IPTOS_THROUGHPUT; options->ip_qos_bulk = IPTOS_THROUGHPUT;
if (options->version_addendum == NULL) if (options->version_addendum == NULL)
options->version_addendum = xstrdup(""); options->version_addendum = xstrdup("");
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
options->fwd_opts.streamlocal_bind_mask = 0177;
if (options->fwd_opts.streamlocal_bind_unlink == -1)
options->fwd_opts.streamlocal_bind_unlink = 0;
/* Turn privilege separation on by default */ /* Turn privilege separation on by default */
if (use_privsep == -1) if (use_privsep == -1)
use_privsep = PRIVSEP_NOSANDBOX; use_privsep = PRIVSEP_NOSANDBOX;
@ -351,6 +360,8 @@ typedef enum {
sKexAlgorithms, sIPQoS, sVersionAddendum, sKexAlgorithms, sIPQoS, sVersionAddendum,
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
sStreamLocalBindMask, sStreamLocalBindUnlink,
sAllowStreamLocalForwarding,
sDeprecated, sUnsupported sDeprecated, sUnsupported
} ServerOpCodes; } ServerOpCodes;
@ -478,6 +489,9 @@ static struct {
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
{ "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
{ NULL, sBadOption, 0 } { NULL, sBadOption, 0 }
}; };
@ -1195,7 +1209,7 @@ process_server_config_line(ServerOptions *options, char *line,
break; break;
case sGatewayPorts: case sGatewayPorts:
intptr = &options->gateway_ports; intptr = &options->fwd_opts.gateway_ports;
multistate_ptr = multistate_gatewayports; multistate_ptr = multistate_gatewayports;
goto parse_multistate; goto parse_multistate;
@ -1230,6 +1244,11 @@ process_server_config_line(ServerOptions *options, char *line,
multistate_ptr = multistate_tcpfwd; multistate_ptr = multistate_tcpfwd;
goto parse_multistate; goto parse_multistate;
case sAllowStreamLocalForwarding:
intptr = &options->allow_streamlocal_forwarding;
multistate_ptr = multistate_tcpfwd;
goto parse_multistate;
case sAllowAgentForwarding: case sAllowAgentForwarding:
intptr = &options->allow_agent_forwarding; intptr = &options->allow_agent_forwarding;
goto parse_flag; goto parse_flag;
@ -1628,6 +1647,22 @@ process_server_config_line(ServerOptions *options, char *line,
} }
return 0; return 0;
case sStreamLocalBindMask:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing StreamLocalBindMask argument.",
filename, linenum);
/* Parse mode in octal format */
value = strtol(arg, &p, 8);
if (arg == p || value < 0 || value > 0777)
fatal("%s line %d: Bad mask.", filename, linenum);
options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
break;
case sStreamLocalBindUnlink:
intptr = &options->fwd_opts.streamlocal_bind_unlink;
goto parse_flag;
case sDeprecated: case sDeprecated:
logit("%s line %d: Deprecated option %s", logit("%s line %d: Deprecated option %s",
filename, linenum, arg); filename, linenum, arg);
@ -1767,9 +1802,10 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
M_CP_INTOPT(permit_empty_passwd); M_CP_INTOPT(permit_empty_passwd);
M_CP_INTOPT(allow_tcp_forwarding); M_CP_INTOPT(allow_tcp_forwarding);
M_CP_INTOPT(allow_streamlocal_forwarding);
M_CP_INTOPT(allow_agent_forwarding); M_CP_INTOPT(allow_agent_forwarding);
M_CP_INTOPT(permit_tun); M_CP_INTOPT(permit_tun);
M_CP_INTOPT(gateway_ports); M_CP_INTOPT(fwd_opts.gateway_ports);
M_CP_INTOPT(x11_display_offset); M_CP_INTOPT(x11_display_offset);
M_CP_INTOPT(x11_forwarding); M_CP_INTOPT(x11_forwarding);
M_CP_INTOPT(x11_use_localhost); M_CP_INTOPT(x11_use_localhost);
@ -1867,6 +1903,8 @@ fmt_intarg(ServerOpCodes code, int val)
return fmt_multistate_int(val, multistate_privsep); return fmt_multistate_int(val, multistate_privsep);
case sAllowTcpForwarding: case sAllowTcpForwarding:
return fmt_multistate_int(val, multistate_tcpfwd); return fmt_multistate_int(val, multistate_tcpfwd);
case sAllowStreamLocalForwarding:
return fmt_multistate_int(val, multistate_tcpfwd);
case sProtocol: case sProtocol:
switch (val) { switch (val) {
case SSH_PROTO_1: case SSH_PROTO_1:
@ -2023,9 +2061,10 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
dump_cfg_fmtint(sUseLogin, o->use_login); dump_cfg_fmtint(sUseLogin, o->use_login);
dump_cfg_fmtint(sCompression, o->compression); dump_cfg_fmtint(sCompression, o->compression);
dump_cfg_fmtint(sGatewayPorts, o->gateway_ports); dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
dump_cfg_fmtint(sUseDNS, o->use_dns); dump_cfg_fmtint(sUseDNS, o->use_dns);
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
/* string arguments */ /* string arguments */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.h,v 1.113 2014/07/03 22:40:43 djm Exp $ */ /* $OpenBSD: servconf.h,v 1.114 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -92,7 +92,7 @@ typedef struct {
char *macs; /* Supported SSH2 macs. */ char *macs; /* Supported SSH2 macs. */
char *kex_algorithms; /* SSH2 kex methods in order of preference. */ char *kex_algorithms; /* SSH2 kex methods in order of preference. */
int protocol; /* Supported protocol versions. */ int protocol; /* Supported protocol versions. */
int gateway_ports; /* If true, allow remote connects to forwarded ports. */ struct ForwardOptions fwd_opts; /* forwarding options */
SyslogFacility log_facility; /* Facility for system logging. */ SyslogFacility log_facility; /* Facility for system logging. */
LogLevel log_level; /* Level for system logging. */ LogLevel log_level; /* Level for system logging. */
int rhosts_rsa_authentication; /* If true, permit rhosts RSA int rhosts_rsa_authentication; /* If true, permit rhosts RSA
@ -124,6 +124,7 @@ typedef struct {
int use_login; /* If true, login(1) is used */ int use_login; /* If true, login(1) is used */
int compression; /* If true, compression is allowed */ int compression; /* If true, compression is allowed */
int allow_tcp_forwarding; /* One of FORWARD_* */ int allow_tcp_forwarding; /* One of FORWARD_* */
int allow_streamlocal_forwarding; /* One of FORWARD_* */
int allow_agent_forwarding; int allow_agent_forwarding;
u_int num_allow_users; u_int num_allow_users;
char *allow_users[MAX_ALLOW_USERS]; char *allow_users[MAX_ALLOW_USERS];

View File

@ -1,4 +1,4 @@
/* $OpenBSD: serverloop.c,v 1.171 2014/04/29 13:10:30 djm Exp $ */ /* $OpenBSD: serverloop.c,v 1.172 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -61,6 +61,7 @@
#include "packet.h" #include "packet.h"
#include "buffer.h" #include "buffer.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "canohost.h" #include "canohost.h"
#include "sshpty.h" #include "sshpty.h"
@ -77,7 +78,6 @@
#include "dispatch.h" #include "dispatch.h"
#include "auth-options.h" #include "auth-options.h"
#include "serverloop.h" #include "serverloop.h"
#include "misc.h"
#include "roaming.h" #include "roaming.h"
extern ServerOptions options; extern ServerOptions options;
@ -970,7 +970,7 @@ server_request_direct_tcpip(void)
/* XXX fine grained permissions */ /* XXX fine grained permissions */
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
!no_port_forwarding_flag) { !no_port_forwarding_flag) {
c = channel_connect_to(target, target_port, c = channel_connect_to_port(target, target_port,
"direct-tcpip", "direct-tcpip"); "direct-tcpip", "direct-tcpip");
} else { } else {
logit("refused local port forward: " logit("refused local port forward: "
@ -984,6 +984,38 @@ server_request_direct_tcpip(void)
return c; return c;
} }
static Channel *
server_request_direct_streamlocal(void)
{
Channel *c = NULL;
char *target, *originator;
u_short originator_port;
target = packet_get_string(NULL);
originator = packet_get_string(NULL);
originator_port = packet_get_int();
packet_check_eom();
debug("server_request_direct_streamlocal: originator %s port %d, target %s",
originator, originator_port, target);
/* XXX fine grained permissions */
if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 &&
!no_port_forwarding_flag) {
c = channel_connect_to_path(target,
"direct-streamlocal@openssh.com", "direct-streamlocal");
} else {
logit("refused streamlocal port forward: "
"originator %s port %d, target %s",
originator, originator_port, target);
}
free(originator);
free(target);
return c;
}
static Channel * static Channel *
server_request_tun(void) server_request_tun(void)
{ {
@ -1081,6 +1113,8 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
c = server_request_session(); c = server_request_session();
} else if (strcmp(ctype, "direct-tcpip") == 0) { } else if (strcmp(ctype, "direct-tcpip") == 0) {
c = server_request_direct_tcpip(); c = server_request_direct_tcpip();
} else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) {
c = server_request_direct_streamlocal();
} else if (strcmp(ctype, "tun@openssh.com") == 0) { } else if (strcmp(ctype, "tun@openssh.com") == 0) {
c = server_request_tun(); c = server_request_tun();
} }
@ -1125,47 +1159,74 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
/* -R style forwarding */ /* -R style forwarding */
if (strcmp(rtype, "tcpip-forward") == 0) { if (strcmp(rtype, "tcpip-forward") == 0) {
struct passwd *pw; struct passwd *pw;
char *listen_address; struct Forward fwd;
u_short listen_port;
pw = the_authctxt->pw; pw = the_authctxt->pw;
if (pw == NULL || !the_authctxt->valid) if (pw == NULL || !the_authctxt->valid)
fatal("server_input_global_request: no/invalid user"); fatal("server_input_global_request: no/invalid user");
listen_address = packet_get_string(NULL); memset(&fwd, 0, sizeof(fwd));
listen_port = (u_short)packet_get_int(); fwd.listen_host = packet_get_string(NULL);
fwd.listen_port = (u_short)packet_get_int();
debug("server_input_global_request: tcpip-forward listen %s port %d", debug("server_input_global_request: tcpip-forward listen %s port %d",
listen_address, listen_port); fwd.listen_host, fwd.listen_port);
/* check permissions */ /* check permissions */
if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 || if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
no_port_forwarding_flag || no_port_forwarding_flag ||
(!want_reply && listen_port == 0) (!want_reply && fwd.listen_port == 0) ||
#ifndef NO_IPPORT_RESERVED_CONCEPT #ifndef NO_IPPORT_RESERVED_CONCEPT
|| (listen_port != 0 && listen_port < IPPORT_RESERVED && (fwd.listen_port != 0 && fwd.listen_port < IPPORT_RESERVED &&
pw->pw_uid != 0) pw->pw_uid != 0)
#endif #endif
) { ) {
success = 0; success = 0;
packet_send_debug("Server has disabled port forwarding."); packet_send_debug("Server has disabled port forwarding.");
} else { } else {
/* Start listening on the port */ /* Start listening on the port */
success = channel_setup_remote_fwd_listener( success = channel_setup_remote_fwd_listener(&fwd,
listen_address, listen_port, &allocated_listen_port, &options.fwd_opts);
&allocated_listen_port, options.gateway_ports);
} }
free(listen_address); free(fwd.listen_host);
} else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
char *cancel_address; struct Forward fwd;
u_short cancel_port;
cancel_address = packet_get_string(NULL); memset(&fwd, 0, sizeof(fwd));
cancel_port = (u_short)packet_get_int(); fwd.listen_host = packet_get_string(NULL);
fwd.listen_port = (u_short)packet_get_int();
debug("%s: cancel-tcpip-forward addr %s port %d", __func__, debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
cancel_address, cancel_port); fwd.listen_host, fwd.listen_port);
success = channel_cancel_rport_listener(cancel_address, success = channel_cancel_rport_listener(&fwd);
cancel_port); free(fwd.listen_host);
free(cancel_address); } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) {
struct Forward fwd;
memset(&fwd, 0, sizeof(fwd));
fwd.listen_path = packet_get_string(NULL);
debug("server_input_global_request: streamlocal-forward listen path %s",
fwd.listen_path);
/* check permissions */
if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0
|| no_port_forwarding_flag) {
success = 0;
packet_send_debug("Server has disabled port forwarding.");
} else {
/* Start listening on the socket */
success = channel_setup_remote_fwd_listener(
&fwd, NULL, &options.fwd_opts);
}
free(fwd.listen_path);
} else if (strcmp(rtype, "cancel-streamlocal-forward@openssh.com") == 0) {
struct Forward fwd;
memset(&fwd, 0, sizeof(fwd));
fwd.listen_path = packet_get_string(NULL);
debug("%s: cancel-streamlocal-forward path %s", __func__,
fwd.listen_path);
success = channel_cancel_rport_listener(&fwd);
free(fwd.listen_path);
} else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
no_more_sessions = 1; no_more_sessions = 1;
success = 1; success = 1;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: session.c,v 1.273 2014/07/03 22:40:43 djm Exp $ */ /* $OpenBSD: session.c,v 1.274 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved * All rights reserved
@ -84,11 +84,11 @@
#include "authfd.h" #include "authfd.h"
#include "pathnames.h" #include "pathnames.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "sshlogin.h" #include "sshlogin.h"
#include "serverloop.h" #include "serverloop.h"
#include "canohost.h" #include "canohost.h"
#include "misc.h"
#include "session.h" #include "session.h"
#include "kex.h" #include "kex.h"
#include "monitor_wrap.h" #include "monitor_wrap.h"
@ -183,7 +183,6 @@ auth_input_request_forwarding(struct passwd * pw)
{ {
Channel *nc; Channel *nc;
int sock = -1; int sock = -1;
struct sockaddr_un sunaddr;
if (auth_sock_name != NULL) { if (auth_sock_name != NULL) {
error("authentication forwarding requested twice."); error("authentication forwarding requested twice.");
@ -209,33 +208,15 @@ auth_input_request_forwarding(struct passwd * pw)
xasprintf(&auth_sock_name, "%s/agent.%ld", xasprintf(&auth_sock_name, "%s/agent.%ld",
auth_sock_dir, (long) getpid()); auth_sock_dir, (long) getpid());
/* Create the socket. */ /* Start a Unix listener on auth_sock_name. */
sock = socket(AF_UNIX, SOCK_STREAM, 0); sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0);
if (sock < 0) {
error("socket: %.100s", strerror(errno));
restore_uid();
goto authsock_err;
}
/* Bind it to the name. */
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
error("bind: %.100s", strerror(errno));
restore_uid();
goto authsock_err;
}
/* Restore the privileged uid. */ /* Restore the privileged uid. */
restore_uid(); restore_uid();
/* Start listening on the socket. */ /* Check for socket/bind/listen failure. */
if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { if (sock < 0)
error("listen: %.100s", strerror(errno));
goto authsock_err; goto authsock_err;
}
/* Allocate a channel for the authentication agent socket. */ /* Allocate a channel for the authentication agent socket. */
nc = channel_new("auth socket", nc = channel_new("auth socket",
@ -274,6 +255,7 @@ do_authenticated(Authctxt *authctxt)
setproctitle("%s", authctxt->pw->pw_name); setproctitle("%s", authctxt->pw->pw_name);
/* setup the channel layer */ /* setup the channel layer */
/* XXX - streamlocal? */
if (no_port_forwarding_flag || if (no_port_forwarding_flag ||
(options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
channel_disable_adm_local_opens(); channel_disable_adm_local_opens();
@ -393,7 +375,7 @@ do_authenticated1(Authctxt *authctxt)
} }
debug("Received TCP/IP port forwarding request."); debug("Received TCP/IP port forwarding request.");
if (channel_input_port_forward_request(s->pw->pw_uid == 0, if (channel_input_port_forward_request(s->pw->pw_uid == 0,
options.gateway_ports) < 0) { &options.fwd_opts) < 0) {
debug("Port forwarding failed."); debug("Port forwarding failed.");
break; break;
} }

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-agent.c,v 1.187 2014/07/03 03:11:03 djm Exp $ */ /* $OpenBSD: ssh-agent.c,v 1.188 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -1038,11 +1038,9 @@ main(int ac, char **av)
u_int nalloc; u_int nalloc;
char *shell, *format, *pidstr, *agentsocket = NULL; char *shell, *format, *pidstr, *agentsocket = NULL;
fd_set *readsetp = NULL, *writesetp = NULL; fd_set *readsetp = NULL, *writesetp = NULL;
struct sockaddr_un sunaddr;
#ifdef HAVE_SETRLIMIT #ifdef HAVE_SETRLIMIT
struct rlimit rlim; struct rlimit rlim;
#endif #endif
int prev_mask;
extern int optind; extern int optind;
extern char *optarg; extern char *optarg;
pid_t pid; pid_t pid;
@ -1161,27 +1159,12 @@ main(int ac, char **av)
* Create socket early so it will exist before command gets run from * Create socket early so it will exist before command gets run from
* the parent. * the parent.
*/ */
sock = socket(AF_UNIX, SOCK_STREAM, 0); sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0);
if (sock < 0) { if (sock < 0) {
perror("socket"); /* XXX - unix_listener() calls error() not perror() */
*socket_name = '\0'; /* Don't unlink any existing file */ *socket_name = '\0'; /* Don't unlink any existing file */
cleanup_exit(1); cleanup_exit(1);
} }
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
prev_mask = umask(0177);
if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) {
perror("bind");
*socket_name = '\0'; /* Don't unlink any existing file */
umask(prev_mask);
cleanup_exit(1);
}
umask(prev_mask);
if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
perror("listen");
cleanup_exit(1);
}
/* /*
* Fork, and have the parent execute the command, if any, or present * Fork, and have the parent execute the command, if any, or present

62
ssh.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh.c,v 1.405 2014/07/03 06:39:19 djm Exp $ */ /* $OpenBSD: ssh.c,v 1.406 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -96,9 +96,9 @@
#include "dispatch.h" #include "dispatch.h"
#include "clientloop.h" #include "clientloop.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "readconf.h" #include "readconf.h"
#include "sshconnect.h" #include "sshconnect.h"
#include "misc.h"
#include "kex.h" #include "kex.h"
#include "mac.h" #include "mac.h"
#include "sshpty.h" #include "sshpty.h"
@ -423,7 +423,7 @@ main(int ac, char **av)
int timeout_ms; int timeout_ms;
extern int optind, optreset; extern int optind, optreset;
extern char *optarg; extern char *optarg;
Forward fwd; struct Forward fwd;
struct addrinfo *addrs = NULL; struct addrinfo *addrs = NULL;
struct ssh_digest_ctx *md; struct ssh_digest_ctx *md;
u_char conn_hash[SSH_DIGEST_MAX_LENGTH]; u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
@ -545,7 +545,7 @@ main(int ac, char **av)
options.forward_x11_trusted = 1; options.forward_x11_trusted = 1;
break; break;
case 'g': case 'g':
options.gateway_ports = 1; options.fwd_opts.gateway_ports = 1;
break; break;
case 'O': case 'O':
if (stdio_forward_host != NULL) if (stdio_forward_host != NULL)
@ -1305,15 +1305,17 @@ fork_postauth(void)
static void static void
ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
{ {
Forward *rfwd = (Forward *)ctxt; struct Forward *rfwd = (struct Forward *)ctxt;
/* XXX verbose() on failure? */ /* XXX verbose() on failure? */
debug("remote forward %s for: listen %s%s%d, connect %s:%d", debug("remote forward %s for: listen %s%s%d, connect %s:%d",
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
rfwd->listen_host == NULL ? "" : rfwd->listen_host, rfwd->listen_path ? rfwd->listen_path :
rfwd->listen_host == NULL ? "" : ":", rfwd->listen_host ? rfwd->listen_host : "",
rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); (rfwd->listen_path || rfwd->listen_host) ? ":" : "",
if (rfwd->listen_port == 0) { rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
rfwd->connect_host, rfwd->connect_port);
if (rfwd->listen_path == NULL && rfwd->listen_port == 0) {
if (type == SSH2_MSG_REQUEST_SUCCESS) { if (type == SSH2_MSG_REQUEST_SUCCESS) {
rfwd->allocated_port = packet_get_int(); rfwd->allocated_port = packet_get_int();
logit("Allocated port %u for remote forward to %s:%d", logit("Allocated port %u for remote forward to %s:%d",
@ -1327,12 +1329,21 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
} }
if (type == SSH2_MSG_REQUEST_FAILURE) { if (type == SSH2_MSG_REQUEST_FAILURE) {
if (options.exit_on_forward_failure) if (options.exit_on_forward_failure) {
fatal("Error: remote port forwarding failed for " if (rfwd->listen_path != NULL)
"listen port %d", rfwd->listen_port); fatal("Error: remote port forwarding failed "
else "for listen path %s", rfwd->listen_path);
logit("Warning: remote port forwarding failed for " else
"listen port %d", rfwd->listen_port); fatal("Error: remote port forwarding failed "
"for listen port %d", rfwd->listen_port);
} else {
if (rfwd->listen_path != NULL)
logit("Warning: remote port forwarding failed "
"for listen path %s", rfwd->listen_path);
else
logit("Warning: remote port forwarding failed "
"for listen port %d", rfwd->listen_port);
}
} }
if (++remote_forward_confirms_received == options.num_remote_forwards) { if (++remote_forward_confirms_received == options.num_remote_forwards) {
debug("All remote forwarding requests processed"); debug("All remote forwarding requests processed");
@ -1380,18 +1391,18 @@ ssh_init_forwarding(void)
for (i = 0; i < options.num_local_forwards; i++) { for (i = 0; i < options.num_local_forwards; i++) {
debug("Local connections to %.200s:%d forwarded to remote " debug("Local connections to %.200s:%d forwarded to remote "
"address %.200s:%d", "address %.200s:%d",
(options.local_forwards[i].listen_path != NULL) ?
options.local_forwards[i].listen_path :
(options.local_forwards[i].listen_host == NULL) ? (options.local_forwards[i].listen_host == NULL) ?
(options.gateway_ports ? "*" : "LOCALHOST") : (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
options.local_forwards[i].listen_host, options.local_forwards[i].listen_host,
options.local_forwards[i].listen_port, options.local_forwards[i].listen_port,
(options.local_forwards[i].connect_path != NULL) ?
options.local_forwards[i].connect_path :
options.local_forwards[i].connect_host, options.local_forwards[i].connect_host,
options.local_forwards[i].connect_port); options.local_forwards[i].connect_port);
success += channel_setup_local_fwd_listener( success += channel_setup_local_fwd_listener(
options.local_forwards[i].listen_host, &options.local_forwards[i], &options.fwd_opts);
options.local_forwards[i].listen_port,
options.local_forwards[i].connect_host,
options.local_forwards[i].connect_port,
options.gateway_ports);
} }
if (i > 0 && success != i && options.exit_on_forward_failure) if (i > 0 && success != i && options.exit_on_forward_failure)
fatal("Could not request local forwarding."); fatal("Could not request local forwarding.");
@ -1402,17 +1413,18 @@ ssh_init_forwarding(void)
for (i = 0; i < options.num_remote_forwards; i++) { for (i = 0; i < options.num_remote_forwards; i++) {
debug("Remote connections from %.200s:%d forwarded to " debug("Remote connections from %.200s:%d forwarded to "
"local address %.200s:%d", "local address %.200s:%d",
(options.remote_forwards[i].listen_path != NULL) ?
options.remote_forwards[i].listen_path :
(options.remote_forwards[i].listen_host == NULL) ? (options.remote_forwards[i].listen_host == NULL) ?
"LOCALHOST" : options.remote_forwards[i].listen_host, "LOCALHOST" : options.remote_forwards[i].listen_host,
options.remote_forwards[i].listen_port, options.remote_forwards[i].listen_port,
(options.remote_forwards[i].connect_path != NULL) ?
options.remote_forwards[i].connect_path :
options.remote_forwards[i].connect_host, options.remote_forwards[i].connect_host,
options.remote_forwards[i].connect_port); options.remote_forwards[i].connect_port);
options.remote_forwards[i].handle = options.remote_forwards[i].handle =
channel_request_remote_forwarding( channel_request_remote_forwarding(
options.remote_forwards[i].listen_host, &options.remote_forwards[i]);
options.remote_forwards[i].listen_port,
options.remote_forwards[i].connect_host,
options.remote_forwards[i].connect_port);
if (options.remote_forwards[i].handle < 0) { if (options.remote_forwards[i].handle < 0) {
if (options.exit_on_forward_failure) if (options.exit_on_forward_failure)
fatal("Could not request remote forwarding."); fatal("Could not request remote forwarding.");

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: ssh_config.5,v 1.190 2014/07/07 08:19:12 djm Exp $ .\" $OpenBSD: ssh_config.5,v 1.191 2014/07/15 15:54:14 millert Exp $
.Dd $Mdocdate: July 7 2014 $ .Dd $Mdocdate: July 15 2014 $
.Dt SSH_CONFIG 5 .Dt SSH_CONFIG 5
.Os .Os
.Sh NAME .Sh NAME
@ -1303,6 +1303,33 @@ channel to request a response from the server.
The default The default
is 0, indicating that these messages will not be sent to the server. is 0, indicating that these messages will not be sent to the server.
This option applies to protocol version 2 only. This option applies to protocol version 2 only.
.It Cm StreamLocalBindMask
Sets the octal file creation mode mask
.Pq umask
used when creating a Unix-domain socket file for local or remote
port forwarding.
This option is only used for port forwarding to a Unix-domain socket file.
.Pp
The default value is 0177, which creates a Unix-domain socket file that is
readable and writable only by the owner.
Note that not all operating systems honor the file mode on Unix-domain
socket files.
.It Cm StreamLocalBindUnlink
Specifies whether to remove an existing Unix-domain socket file for local
or remote port forwarding before creating a new one.
If the socket file already exists and
.Cm StreamLocalBindUnlink
is not enabled,
.Nm ssh
will be unable to forward the port to the Unix-domain socket file.
This option is only used for port forwarding to a Unix-domain socket file.
.Pp
The argument must be
.Dq yes
or
.Dq no .
The default is
.Dq no .
.It Cm StrictHostKeyChecking .It Cm StrictHostKeyChecking
If this flag is set to If this flag is set to
.Dq yes , .Dq yes ,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect.c,v 1.250 2014/07/03 22:23:46 djm Exp $ */ /* $OpenBSD: sshconnect.c,v 1.251 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -54,9 +54,9 @@
#include "sshconnect.h" #include "sshconnect.h"
#include "hostfile.h" #include "hostfile.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "readconf.h" #include "readconf.h"
#include "atomicio.h" #include "atomicio.h"
#include "misc.h"
#include "dns.h" #include "dns.h"
#include "roaming.h" #include "roaming.h"
#include "monitor_fdpass.h" #include "monitor_fdpass.h"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect1.c,v 1.75 2014/06/24 01:13:21 djm Exp $ */ /* $OpenBSD: sshconnect1.c,v 1.76 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -38,11 +38,11 @@
#include "kex.h" #include "kex.h"
#include "uidswap.h" #include "uidswap.h"
#include "log.h" #include "log.h"
#include "misc.h"
#include "readconf.h" #include "readconf.h"
#include "authfd.h" #include "authfd.h"
#include "sshconnect.h" #include "sshconnect.h"
#include "authfile.h" #include "authfile.h"
#include "misc.h"
#include "canohost.h" #include "canohost.h"
#include "hostfile.h" #include "hostfile.h"
#include "auth.h" #include "auth.h"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect2.c,v 1.209 2014/06/24 01:13:21 djm Exp $ */ /* $OpenBSD: sshconnect2.c,v 1.210 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved.
@ -61,8 +61,8 @@
#include "dh.h" #include "dh.h"
#include "authfd.h" #include "authfd.h"
#include "log.h" #include "log.h"
#include "readconf.h"
#include "misc.h" #include "misc.h"
#include "readconf.h"
#include "match.h" #include "match.h"
#include "dispatch.h" #include "dispatch.h"
#include "canohost.h" #include "canohost.h"

4
sshd.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.427 2014/06/24 01:13:21 djm Exp $ */ /* $OpenBSD: sshd.c,v 1.428 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -93,6 +93,7 @@
#include "packet.h" #include "packet.h"
#include "log.h" #include "log.h"
#include "buffer.h" #include "buffer.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
#include "uidswap.h" #include "uidswap.h"
#include "compat.h" #include "compat.h"
@ -108,7 +109,6 @@
#include "hostfile.h" #include "hostfile.h"
#include "auth.h" #include "auth.h"
#include "authfd.h" #include "authfd.h"
#include "misc.h"
#include "msg.h" #include "msg.h"
#include "dispatch.h" #include "dispatch.h"
#include "channels.h" #include "channels.h"

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: sshd_config.5,v 1.174 2014/07/03 22:40:43 djm Exp $ .\" $OpenBSD: sshd_config.5,v 1.175 2014/07/15 15:54:14 millert Exp $
.Dd $Mdocdate: July 3 2014 $ .Dd $Mdocdate: July 15 2014 $
.Dt SSHD_CONFIG 5 .Dt SSHD_CONFIG 5
.Os .Os
.Sh NAME .Sh NAME
@ -140,6 +140,26 @@ The default is
Note that disabling TCP forwarding does not improve security unless Note that disabling TCP forwarding does not improve security unless
users are also denied shell access, as they can always install their users are also denied shell access, as they can always install their
own forwarders. own forwarders.
.It Cm AllowStreamLocalForwarding
Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted.
The available options are
.Dq yes
or
.Dq all
to allow StreamLocal forwarding,
.Dq no
to prevent all StreamLocal forwarding,
.Dq local
to allow local (from the perspective of
.Xr ssh 1 )
forwarding only or
.Dq remote
to allow remote forwarding only.
The default is
.Dq yes .
Note that disabling StreamLocal forwarding does not improve security unless
users are also denied shell access, as they can always install their
own forwarders.
.It Cm AllowUsers .It Cm AllowUsers
This keyword can be followed by a list of user name patterns, separated This keyword can be followed by a list of user name patterns, separated
by spaces. by spaces.
@ -1171,6 +1191,33 @@ This option applies to protocol version 1 only.
.It Cm ServerKeyBits .It Cm ServerKeyBits
Defines the number of bits in the ephemeral protocol version 1 server key. Defines the number of bits in the ephemeral protocol version 1 server key.
The minimum value is 512, and the default is 1024. The minimum value is 512, and the default is 1024.
.It Cm StreamLocalBindMask
Sets the octal file creation mode mask
.Pq umask
used when creating a Unix-domain socket file for local or remote
port forwarding.
This option is only used for port forwarding to a Unix-domain socket file.
.Pp
The default value is 0177, which creates a Unix-domain socket file that is
readable and writable only by the owner.
Note that not all operating systems honor the file mode on Unix-domain
socket files.
.It Cm StreamLocalBindUnlink
Specifies whether to remove an existing Unix-domain socket file for local
or remote port forwarding before creating a new one.
If the socket file already exists and
.Cm StreamLocalBindUnlink
is not enabled,
.Nm sshd
will be unable to forward the port to the Unix-domain socket file.
This option is only used for port forwarding to a Unix-domain socket file.
.Pp
The argument must be
.Dq yes
or
.Dq no .
The default is
.Dq no .
.It Cm StrictModes .It Cm StrictModes
Specifies whether Specifies whether
.Xr sshd 8 .Xr sshd 8

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshlogin.c,v 1.28 2014/01/31 16:39:19 tedu Exp $ */ /* $OpenBSD: sshlogin.c,v 1.29 2014/07/15 15:54:14 millert Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -58,6 +58,7 @@
#include "loginrec.h" #include "loginrec.h"
#include "log.h" #include "log.h"
#include "buffer.h" #include "buffer.h"
#include "misc.h"
#include "servconf.h" #include "servconf.h"
extern Buffer loginmsg; extern Buffer loginmsg;