[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
- (djm) [digest-openssl.c] Preserve array order when disabling digests.
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
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.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
"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 "auth.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
/* limited protocol v1 interface to kbd-interactive authentication */

View File

@ -40,6 +40,7 @@
#include "packet.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "uidswap.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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -26,9 +26,9 @@
#include "log.h"
#include "canohost.h"
#include "buffer.h"
#include "misc.h"
#include "channels.h"
#include "servconf.h"
#include "misc.h"
#include "key.h"
#include "auth-options.h"
#include "hostfile.h"
@ -325,6 +325,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
patterns[i] = '\0';
opts++;
p = patterns;
/* XXX - add streamlocal support */
host = hpdelim(&p);
if (host == NULL || strlen(host) >= NI_MAXHOST) {
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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -48,6 +48,7 @@
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "key.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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -24,6 +24,7 @@
#include "uidswap.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "key.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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -34,12 +34,12 @@
#include "uidswap.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "canohost.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "misc.h"
/* import */
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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -35,6 +35,7 @@
#include "buffer.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "key.h"
#include "auth-options.h"
@ -45,7 +46,6 @@
#endif
#include "monitor_wrap.h"
#include "ssh.h"
#include "misc.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.
*
@ -56,6 +56,7 @@
#include "groupaccess.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "key.h"
#include "hostfile.h"
@ -63,7 +64,6 @@
#include "auth-options.h"
#include "canohost.h"
#include "uidswap.h"
#include "misc.h"
#include "packet.h"
#include "loginrec.h"
#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
* All rights reserved
@ -27,6 +27,7 @@
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "key.h"

View File

@ -41,6 +41,7 @@
#include "packet.h"
#include "dispatch.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
/* 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.
*
@ -36,6 +36,7 @@
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "compat.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.
*
@ -36,6 +36,7 @@
#include "auth.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
/* 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.
*
@ -43,6 +43,7 @@
#include "packet.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "compat.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.
*
@ -41,6 +41,7 @@
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "misc.h"
#include "servconf.h"
/* 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.
*
@ -48,6 +48,7 @@
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "key.h"
@ -61,7 +62,6 @@
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "misc.h"
#include "authfile.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.
*
@ -41,6 +41,7 @@
#include "packet.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "compat.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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -16,6 +16,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@ -262,6 +263,11 @@ get_socket_address(int sock, int remote, int flags)
if (addr.ss_family == AF_INET6)
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);
/* Get the address in ascii. */
@ -384,6 +390,10 @@ get_sock_port(int sock, int local)
if (from.ss_family == AF_INET6)
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. */
if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -42,6 +42,7 @@
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/un.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
* 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 {
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. */
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;
/* 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_RPORT_LISTENER:
case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
channel_close_fd(&c->sock);
channel_free(c);
break;
@ -536,6 +543,8 @@ channel_still_open(void)
case SSH_CHANNEL_CONNECTING:
case SSH_CHANNEL_ZOMBIE:
case SSH_CHANNEL_ABANDONED:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
continue;
case SSH_CHANNEL_LARVAL:
if (!compat20)
@ -582,6 +591,8 @@ channel_find_open(void)
case SSH_CHANNEL_CONNECTING:
case SSH_CHANNEL_ZOMBIE:
case SSH_CHANNEL_ABANDONED:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
continue;
case SSH_CHANNEL_LARVAL:
case SSH_CHANNEL_AUTH_SOCKET:
@ -632,6 +643,8 @@ channel_open_message(void)
case SSH_CHANNEL_ABANDONED:
case SSH_CHANNEL_MUX_CLIENT:
case SSH_CHANNEL_MUX_LISTENER:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
continue;
case SSH_CHANNEL_LARVAL:
case SSH_CHANNEL_OPENING:
@ -1387,7 +1400,6 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
static void
port_open_helper(Channel *c, char *rtype)
{
int direct;
char buf[1024];
char *local_ipaddr = get_local_ipaddr(c->sock);
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;
}
direct = (strcmp(rtype, "direct-tcpip") == 0);
snprintf(buf, sizeof buf,
"%s: listening port %d for %.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->local_window_max);
packet_put_int(c->local_maxpacket);
if (direct) {
if (strcmp(rtype, "direct-tcpip") == 0) {
/* target host, port */
packet_put_cstring(c->path);
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 {
/* listen address, port */
packet_put_cstring(c->path);
packet_put_int(local_port);
}
/* originator host and port */
packet_put_cstring(remote_ipaddr);
packet_put_int((u_int)remote_port);
if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
/* reserved for future owner/mode info */
packet_put_cstring("");
} else {
/* originator host and port */
packet_put_cstring(remote_ipaddr);
packet_put_int((u_int)remote_port);
}
packet_send();
} else {
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) {
nextstate = SSH_CHANNEL_OPENING;
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 {
if (c->host_port == 0) {
nextstate = SSH_CHANNEL_DYNAMIC;
rtype = "dynamic-tcpip";
} else {
nextstate = SSH_CHANNEL_OPENING;
rtype = "direct-tcpip";
}
nextstate = SSH_CHANNEL_OPENING;
rtype = "direct-tcpip";
}
addrlen = sizeof(addr);
@ -1499,7 +1524,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
c->notbefore = monotime() + 1;
return;
}
set_nodelay(newsock);
if (c->host_port != PORT_STREAMLOCAL)
set_nodelay(newsock);
nc = channel_new(rtype, nextstate, newsock, newsock, -1,
c->local_window_max, c->local_maxpacket, 0, rtype, 1);
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_PORT_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_AUTH_SOCKET] = &channel_pre_listener;
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_PORT_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_AUTH_SOCKET] = &channel_post_auth_listener;
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)");
}
packet_check_eom();
c = channel_connect_to(host, host_port,
c = channel_connect_to_port(host, host_port,
"connected socket", originator_string);
free(originator_string);
free(host);
@ -2705,20 +2735,20 @@ channel_set_af(int af)
*/
static const char *
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;
int wildcard = 0;
if (listen_addr == NULL) {
/* No address specified: default to gateway_ports setting */
if (gateway_ports)
if (fwd_opts->gateway_ports)
wildcard = 1;
} else if (gateway_ports || is_client) {
} else if (fwd_opts->gateway_ports || is_client) {
if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
*listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
(!is_client && gateway_ports == 1)) {
(!is_client && fwd_opts->gateway_ports == 1)) {
wildcard = 1;
/*
* Notify client if they requested a specific listen
@ -2752,9 +2782,8 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
}
static int
channel_setup_fwd_listener(int type, const char *listen_addr,
u_short listen_port, int *allocated_listen_port,
const char *host_to_connect, u_short port_to_connect, int gateway_ports)
channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
int *allocated_listen_port, struct ForwardOptions *fwd_opts)
{
Channel *c;
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;
host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
listen_addr : host_to_connect;
fwd->listen_host : fwd->connect_host;
is_client = (type == SSH_CHANNEL_PORT_LISTENER);
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 */
addr = channel_fwd_bind_addr(listen_addr, &wildcard,
is_client, gateway_ports);
debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s",
addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard,
is_client, fwd_opts);
debug3("%s: type %d wildcard %d addr %s", __func__,
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_flags = wildcard ? AI_PASSIVE : 0;
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 (addr == NULL) {
/* This really shouldn't happen */
packet_disconnect("getaddrinfo: fatal error: %s",
ssh_gai_strerror(r));
} else {
error("channel_setup_fwd_listener: "
"getaddrinfo(%.64s): %s", addr,
error("%s: getaddrinfo(%.64s): %s", __func__, addr,
ssh_gai_strerror(r));
}
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
* 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)
*lport_p = htons(*allocated_listen_port);
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
error("channel_setup_fwd_listener: getnameinfo failed");
error("%s: getnameinfo failed", __func__);
continue;
}
/* 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.
*/
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 = 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,
0, "port listener", 1);
c->path = xstrdup(host);
c->host_port = port_to_connect;
c->host_port = fwd->connect_port;
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))
c->listening_port = *allocated_listen_port;
else
c->listening_port = listen_port;
c->listening_port = fwd->listen_port;
success = 1;
}
if (success == 0)
error("channel_setup_fwd_listener: cannot listen to port: %d",
listen_port);
error("%s: cannot listen to port: %d", __func__,
fwd->listen_port);
freeaddrinfo(aitop);
return success;
}
int
channel_cancel_rport_listener(const char *host, u_short port)
static int
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;
int found = 0;
@ -2917,13 +3019,44 @@ channel_cancel_rport_listener(const char *host, u_short port)
return (found);
}
int
channel_cancel_lport_listener(const char *lhost, u_short lport,
int cport, int gateway_ports)
static int
channel_cancel_rport_listener_streamlocal(const char *path)
{
u_int i;
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++) {
Channel *c = channels[i];
@ -2952,24 +3085,68 @@ channel_cancel_lport_listener(const char *lhost, u_short lport,
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) */
int
channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,
const char *host_to_connect, u_short port_to_connect, int gateway_ports)
channel_setup_local_fwd_listener(struct Forward *fwd, struct ForwardOptions *fwd_opts)
{
return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
listen_host, listen_port, NULL, host_to_connect, port_to_connect,
gateway_ports);
if (fwd->listen_path != NULL) {
return channel_setup_fwd_listener_streamlocal(
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 */
int
channel_setup_remote_fwd_listener(const char *listen_address,
u_short listen_port, int *allocated_listen_port, int gateway_ports)
channel_setup_remote_fwd_listener(struct Forward *fwd,
int *allocated_listen_port, struct ForwardOptions *fwd_opts)
{
return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER,
listen_address, listen_port, allocated_listen_port,
NULL, 0, gateway_ports);
if (fwd->listen_path != NULL) {
return channel_setup_fwd_listener_streamlocal(
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().
*/
int
channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
const char *host_to_connect, u_short port_to_connect)
channel_request_remote_forwarding(struct Forward *fwd)
{
int type, success = 0, idx = -1;
/* Send the forward request to the remote side. */
if (compat20) {
packet_start(SSH2_MSG_GLOBAL_REQUEST);
packet_put_cstring("tcpip-forward");
packet_put_char(1); /* boolean: want reply */
packet_put_cstring(channel_rfwd_bind_host(listen_host));
packet_put_int(listen_port);
if (fwd->listen_path != NULL) {
packet_put_cstring("streamlocal-forward@openssh.com");
packet_put_char(1); /* boolean: want reply */
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_write_wait();
/* Assume that server accepts the request */
success = 1;
} else {
} else if (fwd->listen_path == NULL) {
packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
packet_put_int(listen_port);
packet_put_cstring(host_to_connect);
packet_put_int(port_to_connect);
packet_put_int(fwd->listen_port);
packet_put_cstring(fwd->connect_host);
packet_put_int(fwd->connect_port);
packet_send();
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:"
"received packet type %d.", type);
}
} else {
logit("Warning: Server does not support remote stream local forwarding.");
}
if (success) {
/* Record that connection to this host/port is permitted. */
permitted_opens = xrealloc(permitted_opens,
num_permitted_opens + 1, sizeof(*permitted_opens));
idx = num_permitted_opens++;
permitted_opens[idx].host_to_connect = xstrdup(host_to_connect);
permitted_opens[idx].port_to_connect = port_to_connect;
permitted_opens[idx].listen_host = listen_host ?
xstrdup(listen_host) : NULL;
permitted_opens[idx].listen_port = listen_port;
if (fwd->connect_path != NULL) {
permitted_opens[idx].host_to_connect =
xstrdup(fwd->connect_path);
permitted_opens[idx].port_to_connect =
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);
}
static int
open_match(ForwardPermission *allowed_open, const char *requestedhost,
u_short requestedport)
int requestedport)
{
if (allowed_open->host_to_connect == NULL)
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
* need to translate between the configured-host (listen_host)
* and what we've sent to the remote server (channel_rfwd_bind_host)
*/
static int
open_listen_match(ForwardPermission *allowed_open, const char *requestedhost,
u_short requestedport, int translate)
open_listen_match_tcpip(ForwardPermission *allowed_open,
const char *requestedhost, u_short requestedport, int translate)
{
const char *allowed_host;
@ -3094,12 +3295,26 @@ open_listen_match(ForwardPermission *allowed_open, const char *requestedhost,
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
* local side.
*/
int
channel_request_rforward_cancel(const char *host, u_short port)
static int
channel_request_rforward_cancel_tcpip(const char *host, u_short port)
{
int i;
@ -3107,7 +3322,7 @@ channel_request_rforward_cancel(const char *host, u_short port)
return -1;
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;
}
if (i >= num_permitted_opens) {
@ -3121,52 +3336,104 @@ channel_request_rforward_cancel(const char *host, u_short port)
packet_put_int(port);
packet_send();
permitted_opens[i].port_to_connect = 0;
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;
free(permitted_opens[i].listen_host);
permitted_opens[i].listen_host = NULL;
permitted_opens[i].listen_path = NULL;
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
* listening for the port, and sends back a success reply (or disconnect
* message if there was an error).
*/
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;
char *hostname;
struct Forward fwd;
/* Get arguments from the packet. */
port = packet_get_int();
hostname = packet_get_string(NULL);
host_port = packet_get_int();
memset(&fwd, 0, sizeof(fwd));
fwd.listen_port = packet_get_int();
fwd.connect_host = packet_get_string(NULL);
fwd.connect_port = packet_get_int();
#ifndef HAVE_CYGWIN
/*
* Check that an unprivileged user is not trying to forward a
* privileged port.
*/
if (port < IPPORT_RESERVED && !is_root)
if (fwd.listen_port < IPPORT_RESERVED && !is_root)
packet_disconnect(
"Requested forwarding of port %d but user is not root.",
port);
if (host_port == 0)
fwd.listen_port);
if (fwd.connect_port == 0)
packet_disconnect("Dynamic forwarding denied.");
#endif
/* Initiate forwarding */
success = channel_setup_local_fwd_listener(NULL, port, hostname,
host_port, gateway_ports);
success = channel_setup_local_fwd_listener(&fwd, fwd_opts);
/* Free the argument string. */
free(hostname);
free(fwd.connect_host);
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].port_to_connect = port;
permitted_opens[num_permitted_opens].listen_host = NULL;
permitted_opens[num_permitted_opens].listen_path = NULL;
permitted_opens[num_permitted_opens].listen_port = 0;
num_permitted_opens++;
@ -3227,6 +3495,8 @@ channel_update_permitted_opens(int idx, int newport)
permitted_opens[idx].host_to_connect = NULL;
free(permitted_opens[idx].listen_host);
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);
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_path = NULL;
permitted_adm_opens[num_adm_permitted_opens].listen_port = 0;
return ++num_adm_permitted_opens;
}
@ -3262,6 +3533,7 @@ channel_clear_permitted_opens(void)
for (i = 0; i < num_permitted_opens; i++) {
free(permitted_opens[i].host_to_connect);
free(permitted_opens[i].listen_host);
free(permitted_opens[i].listen_path);
}
free(permitted_opens);
permitted_opens = NULL;
@ -3276,6 +3548,7 @@ channel_clear_adm_permitted_opens(void)
for (i = 0; i < num_adm_permitted_opens; i++) {
free(permitted_adm_opens[i].host_to_connect);
free(permitted_adm_opens[i].listen_host);
free(permitted_adm_opens[i].listen_path);
}
free(permitted_adm_opens);
permitted_adm_opens = NULL;
@ -3319,16 +3592,27 @@ static int
connect_next(struct channel_connect *cctx)
{
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) {
if (cctx->ai->ai_family != AF_INET &&
cctx->ai->ai_family != AF_INET6)
continue;
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");
switch (cctx->ai->ai_family) {
case AF_UNIX:
/* unix:pathname instead of host:port */
sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr;
strlcpy(ntop, "unix", sizeof(ntop));
strlcpy(strport, sunaddr->sun_path, sizeof(strport));
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;
}
if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
@ -3351,10 +3635,11 @@ connect_next(struct channel_connect *cctx)
errno = saved_errno;
continue; /* fail -- try next */
}
if (cctx->ai->ai_family != AF_UNIX)
set_nodelay(sock);
debug("connect_next: host %.100s ([%.100s]:%s) "
"in progress, fd=%d", cctx->host, ntop, strport, sock);
cctx->ai = cctx->ai->ai_next;
set_nodelay(sock);
return sock;
}
return -1;
@ -3364,14 +3649,18 @@ static void
channel_connect_ctx_free(struct channel_connect *cctx)
{
free(cctx->host);
if (cctx->aitop)
freeaddrinfo(cctx->aitop);
if (cctx->aitop) {
if (cctx->aitop->ai_family == AF_UNIX)
free(cctx->aitop);
else
freeaddrinfo(cctx->aitop);
}
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 *
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;
int gaierr;
@ -3381,23 +3670,51 @@ connect_to(const char *host, u_short port, char *ctype, char *rname)
Channel *c;
memset(&cctx, 0, sizeof(cctx));
memset(&hints, 0, sizeof(hints));
hints.ai_family = IPv4or6;
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", port);
if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) {
error("connect_to %.100s: unknown host (%s)", host,
ssh_gai_strerror(gaierr));
return NULL;
if (port == PORT_STREAMLOCAL) {
struct sockaddr_un *sunaddr;
struct addrinfo *ai;
if (strlen(name) > sizeof(sunaddr->sun_path)) {
error("%.100s: %.100s", name, strerror(ENAMETOOLONG));
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.ai = cctx.aitop;
if ((sock = connect_next(&cctx)) == -1) {
error("connect to %.100s port %d failed: %s",
host, port, strerror(errno));
name, port, strerror(errno));
channel_connect_ctx_free(&cctx);
return NULL;
}
@ -3414,7 +3731,7 @@ channel_connect_by_listen_address(const char *listen_host,
int 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)) {
return connect_to(
permitted_opens[i].host_to_connect,
@ -3426,9 +3743,26 @@ channel_connect_by_listen_address(const char *listen_host,
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. */
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;
@ -3458,6 +3792,38 @@ channel_connect_to(const char *host, u_short port, char *ctype, char *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
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>
@ -56,7 +56,9 @@
#define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */
#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */
#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
@ -254,6 +256,8 @@ char *channel_open_message(void);
int channel_find_open(void);
/* tcp forwarding */
struct Forward;
struct ForwardOptions;
void channel_set_af(int af);
void channel_permit_all_opens(void);
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_adm_permitted_opens(void);
void channel_print_adm_permitted_opens(void);
int channel_input_port_forward_request(int, int);
Channel *channel_connect_to(const char *, u_short, char *, char *);
int channel_input_port_forward_request(int, struct ForwardOptions *);
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_by_listen_address(const char *, u_short,
char *, char *);
int channel_request_remote_forwarding(const char *, u_short,
const char *, u_short);
int channel_setup_local_fwd_listener(const char *, u_short,
const char *, u_short, int);
int channel_request_rforward_cancel(const char *host, u_short port);
int channel_setup_remote_fwd_listener(const char *, u_short, int *, int);
int channel_cancel_rport_listener(const char *, u_short);
int channel_cancel_lport_listener(const char *, u_short, int, int);
Channel *channel_connect_by_listen_path(const char *, char *, char *);
int channel_request_remote_forwarding(struct Forward *);
int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *);
int channel_request_rforward_cancel(struct Forward *);
int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *);
int channel_cancel_rport_listener(struct Forward *);
int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *);
int permitopen_port(const char *);
/* 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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -100,13 +100,13 @@
#include "cipher.h"
#include "kex.h"
#include "log.h"
#include "misc.h"
#include "readconf.h"
#include "clientloop.h"
#include "sshconnect.h"
#include "authfd.h"
#include "atomicio.h"
#include "sshpty.h"
#include "misc.h"
#include "match.h"
#include "msg.h"
#include "roaming.h"
@ -871,13 +871,11 @@ static void
process_cmdline(void)
{
void (*handler)(int);
char *s, *cmd, *cancel_host;
int delete = 0, local = 0, remote = 0, dynamic = 0;
int cancel_port, ok;
Forward fwd;
char *s, *cmd;
int ok, delete = 0, local = 0, remote = 0, dynamic = 0;
struct Forward fwd;
memset(&fwd, 0, sizeof(fwd));
fwd.listen_host = fwd.connect_host = NULL;
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
handler = signal(SIGINT, SIG_IGN);
@ -943,29 +941,20 @@ process_cmdline(void)
/* XXX update list of forwards in options */
if (delete) {
cancel_port = 0;
cancel_host = hpdelim(&s); /* may be NULL */
if (s != NULL) {
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");
/* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */
if (!parse_forward(&fwd, s, 1, 0)) {
logit("Bad forwarding close specification.");
goto out;
}
if (remote)
ok = channel_request_rforward_cancel(cancel_host,
cancel_port) == 0;
ok = channel_request_rforward_cancel(&fwd) == 0;
else if (dynamic)
ok = channel_cancel_lport_listener(cancel_host,
cancel_port, 0, options.gateway_ports) > 0;
ok = channel_cancel_lport_listener(&fwd,
0, &options.fwd_opts) > 0;
else
ok = channel_cancel_lport_listener(cancel_host,
cancel_port, CHANNEL_CANCEL_PORT_STATIC,
options.gateway_ports) > 0;
ok = channel_cancel_lport_listener(&fwd,
CHANNEL_CANCEL_PORT_STATIC,
&options.fwd_opts) > 0;
if (!ok) {
logit("Unkown port forwarding.");
goto out;
@ -977,16 +966,13 @@ process_cmdline(void)
goto out;
}
if (local || dynamic) {
if (!channel_setup_local_fwd_listener(fwd.listen_host,
fwd.listen_port, fwd.connect_host,
fwd.connect_port, options.gateway_ports)) {
if (!channel_setup_local_fwd_listener(&fwd,
&options.fwd_opts)) {
logit("Port forwarding failed.");
goto out;
}
} else {
if (channel_request_remote_forwarding(fwd.listen_host,
fwd.listen_port, fwd.connect_host,
fwd.connect_port) < 0) {
if (channel_request_remote_forwarding(&fwd) < 0) {
logit("Port forwarding failed.");
goto out;
}
@ -999,7 +985,9 @@ out:
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
free(cmd);
free(fwd.listen_host);
free(fwd.listen_path);
free(fwd.connect_host);
free(fwd.connect_path);
}
/* 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();
packet_check_eom();
debug("client_request_forwarded_tcpip: listen %s port %d, "
"originator %s port %d", listen_address, listen_port,
originator_address, originator_port);
debug("%s: listen %s port %d, originator %s port %d", __func__,
listen_address, listen_port, originator_address, originator_port);
c = channel_connect_by_listen_address(listen_address, listen_port,
"forwarded-tcpip", originator_address);
@ -1857,6 +1844,27 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
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 *
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) {
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) {
c = client_request_x11(ctype, rchan);
} 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) 2005,2006 Damien Miller. All rights reserved.
@ -29,6 +29,7 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/param.h>
#include <stdarg.h>
@ -1056,6 +1057,52 @@ lowercase(char *s)
for (; *s; 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
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>
@ -15,6 +15,25 @@
#ifndef _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 */
char *chop(char *);
@ -37,6 +56,7 @@ void ms_subtract_diff(struct timeval *, int *);
void ms_to_timeval(struct timeval *, int);
time_t monotime(void);
void lowercase(char *s);
int unix_listener(const char *, int, 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_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 */
u_int64_t get_u64(const void *)
__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 Markus Friedl <markus@openbsd.org>
@ -87,6 +87,7 @@
#include "sshlogin.h"
#include "canohost.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "monitor.h"
#include "monitor_mm.h"
@ -95,7 +96,6 @@
#endif
#include "monitor_wrap.h"
#include "monitor_fdpass.h"
#include "misc.h"
#include "compat.h"
#include "ssh2.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>
*
@ -509,29 +509,33 @@ process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r)
}
static char *
format_forward(u_int ftype, Forward *fwd)
format_forward(u_int ftype, struct Forward *fwd)
{
char *ret;
switch (ftype) {
case MUX_FWD_LOCAL:
xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d",
(fwd->listen_path != NULL) ? fwd->listen_path :
(fwd->listen_host == NULL) ?
(options.gateway_ports ? "*" : "LOCALHOST") :
(options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
fwd->listen_host, fwd->listen_port,
(fwd->connect_path != NULL) ? fwd->connect_path :
fwd->connect_host, fwd->connect_port);
break;
case MUX_FWD_DYNAMIC:
xasprintf(&ret, "dynamic forward %.200s:%d -> *",
(fwd->listen_host == NULL) ?
(options.gateway_ports ? "*" : "LOCALHOST") :
(options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
fwd->listen_host, fwd->listen_port);
break;
case MUX_FWD_REMOTE:
xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d",
(fwd->listen_path != NULL) ? fwd->listen_path :
(fwd->listen_host == NULL) ?
"LOCALHOST" : fwd->listen_host,
fwd->listen_port,
(fwd->connect_path != NULL) ? fwd->connect_path :
fwd->connect_host, fwd->connect_port);
break;
default:
@ -551,14 +555,18 @@ compare_host(const char *a, const char *b)
}
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))
return 0;
if (!compare_host(a->listen_path, b->listen_path))
return 0;
if (a->listen_port != b->listen_port)
return 0;
if (!compare_host(a->connect_host, b->connect_host))
return 0;
if (!compare_host(a->connect_path, b->connect_path))
return 0;
if (a->connect_port != b->connect_port)
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;
char *failmsg = NULL;
Forward *rfwd;
struct Forward *rfwd;
Channel *c;
Buffer out;
@ -587,7 +595,8 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
rfwd = &options.remote_forwards[fctx->fid];
debug("%s: %s for: listen %d, connect %s:%d", __func__,
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 (rfwd->listen_port == 0) {
rfwd->allocated_port = packet_get_int();
@ -607,8 +616,12 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
} else {
if (rfwd->listen_port == 0)
channel_update_permitted_opens(rfwd->handle, -1);
xasprintf(&failmsg, "remote port forwarding failed for "
"listen port %d", rfwd->listen_port);
if (rfwd->listen_path != NULL)
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:
error("%s: %s", __func__, failmsg);
@ -627,33 +640,45 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
static int
process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
{
Forward fwd;
struct Forward fwd;
char *fwd_desc = NULL;
char *listen_addr, *connect_addr;
u_int ftype;
u_int lport, cport;
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 ||
(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 ||
(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 ||
lport > 65535 || cport > 65535) {
(lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
error("%s: malformed message", __func__);
ret = -1;
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;
if (fwd.listen_port == PORT_STREAMLOCAL)
fwd.listen_path = listen_addr;
else
fwd.listen_host = listen_addr;
fwd.connect_port = cport;
if (*fwd.listen_host == '\0') {
free(fwd.listen_host);
fwd.listen_host = NULL;
}
if (*fwd.connect_host == '\0') {
free(fwd.connect_host);
fwd.connect_host = NULL;
}
if (fwd.connect_port == PORT_STREAMLOCAL)
fwd.connect_path = connect_addr;
else
fwd.connect_host = connect_addr;
debug2("%s: channel %d: request %s", __func__, c->self,
(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) {
logit("%s: invalid forwarding type %u", __func__, ftype);
invalid:
free(fwd.listen_host);
free(fwd.connect_host);
free(listen_addr);
free(connect_addr);
buffer_put_int(r, MUX_S_FAILURE);
buffer_put_int(r, rid);
buffer_put_cstring(r, "Invalid forwarding request");
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__,
fwd.listen_port);
goto invalid;
}
if (fwd.connect_port >= 65536 || (ftype != MUX_FWD_DYNAMIC &&
ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) {
if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536)
|| (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) {
logit("%s: invalid connect port %u", __func__,
fwd.connect_port);
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__);
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 (!channel_setup_local_fwd_listener(fwd.listen_host,
fwd.listen_port, fwd.connect_host, fwd.connect_port,
options.gateway_ports)) {
if (!channel_setup_local_fwd_listener(&fwd,
&options.fwd_opts)) {
fail:
logit("slave-requested %s failed", fwd_desc);
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 {
struct mux_channel_confirm_ctx *fctx;
fwd.handle = channel_request_remote_forwarding(fwd.listen_host,
fwd.listen_port, fwd.connect_host, fwd.connect_port);
fwd.handle = channel_request_remote_forwarding(&fwd);
if (fwd.handle < 0)
goto fail;
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);
if (freefwd) {
free(fwd.listen_host);
free(fwd.listen_path);
free(fwd.connect_host);
free(fwd.connect_path);
}
return ret;
}
@ -776,36 +806,47 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
static int
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;
const char *error_reason = NULL;
char *listen_addr = NULL, *connect_addr = NULL;
u_int ftype;
int i, listen_port, ret = 0;
int i, ret = 0;
u_int lport, cport;
fwd.listen_host = fwd.connect_host = NULL;
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 ||
(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 ||
lport > 65535 || cport > 65535) {
(lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
error("%s: malformed message", __func__);
ret = -1;
goto out;
}
fwd.listen_port = lport;
fwd.connect_port = cport;
if (*fwd.listen_host == '\0') {
free(fwd.listen_host);
fwd.listen_host = NULL;
if (*listen_addr == '\0') {
free(listen_addr);
listen_addr = NULL;
}
if (*fwd.connect_host == '\0') {
free(fwd.connect_host);
fwd.connect_host = NULL;
if (*connect_addr == '\0') {
free(connect_addr);
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,
(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
* between options.remote_forwards and permitted_opens.
* 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) ?
found_fwd->allocated_port : fwd.listen_port;
if (channel_request_rforward_cancel(fwd.listen_host,
listen_port) == -1)
if (channel_request_rforward_cancel(found_fwd) == -1)
error_reason = "port not in permitted opens";
} else { /* local and dynamic forwards */
/* Ditto */
if (channel_cancel_lport_listener(fwd.listen_host,
fwd.listen_port, fwd.connect_port,
options.gateway_ports) == -1)
if (channel_cancel_lport_listener(&fwd, fwd.connect_port,
&options.fwd_opts) == -1)
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);
free(found_fwd->listen_host);
free(found_fwd->listen_path);
free(found_fwd->connect_host);
free(found_fwd->connect_path);
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;
} else {
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:
free(fwd_desc);
free(fwd.listen_host);
free(fwd.connect_host);
free(listen_addr);
free(connect_addr);
return ret;
}
@ -1133,8 +1173,6 @@ mux_tty_alloc_failed(Channel *c)
void
muxserver_listen(void)
{
struct sockaddr_un addr;
socklen_t sun_len;
mode_t old_umask;
char *orig_control_path = options.control_path;
char rbuf[16+1];
@ -1163,23 +1201,10 @@ muxserver_listen(void)
xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf);
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);
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) {
error("ControlSocket %s already exists, "
"disabling multiplexing", options.control_path);
@ -1193,13 +1218,11 @@ muxserver_listen(void)
options.control_path = NULL;
options.control_master = SSHCTL_MASTER_NO;
return;
} else
fatal("%s bind(): %s", __func__, strerror(errno));
} else {
/* 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 */
if (link(options.control_path, orig_control_path) != 0) {
@ -1593,7 +1616,7 @@ mux_client_request_terminate(int fd)
}
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;
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, muxclient_request_id);
buffer_put_int(&m, ftype);
buffer_put_cstring(&m,
fwd->listen_host == NULL ? "" : fwd->listen_host);
if (fwd->listen_path != NULL) {
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_cstring(&m,
fwd->connect_host == NULL ? "" : fwd->connect_host);
if (fwd->connect_path != NULL) {
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);
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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -66,7 +66,6 @@
#include "crc32.h"
#include "compress.h"
#include "deattack.h"
#include "channels.h"
#include "compat.h"
#include "ssh1.h"
#include "ssh2.h"
@ -77,6 +76,7 @@
#include "log.h"
#include "canohost.h"
#include "misc.h"
#include "channels.h"
#include "ssh.h"
#include "ssherr.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.
@ -25,6 +25,7 @@
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "key.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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -18,6 +18,7 @@
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
@ -48,9 +49,9 @@
#include "pathnames.h"
#include "log.h"
#include "key.h"
#include "misc.h"
#include "readconf.h"
#include "match.h"
#include "misc.h"
#include "buffer.h"
#include "kex.h"
#include "mac.h"
@ -149,6 +150,7 @@ typedef enum {
oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
oStreamLocalBindMask, oStreamLocalBindUnlink,
oIgnoredUnknownOption, oDeprecated, oUnsupported
} OpCodes;
@ -261,6 +263,8 @@ static struct {
{ "canonicalizehostname", oCanonicalizeHostname },
{ "canonicalizemaxdots", oCanonicalizeMaxDots },
{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
{ "streamlocalbindmask", oStreamLocalBindMask },
{ "streamlocalbindunlink", oStreamLocalBindUnlink },
{ "ignoreunknown", oIgnoreUnknown },
{ NULL, oBadOption }
@ -272,12 +276,13 @@ static struct {
*/
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
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.");
#endif
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_port = newfwd->listen_port;
fwd->listen_path = newfwd->listen_path;
fwd->connect_host = newfwd->connect_host;
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
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->num_remote_forwards + 1,
@ -308,8 +315,10 @@ add_remote_forward(Options *options, const Forward *newfwd)
fwd->listen_host = newfwd->listen_host;
fwd->listen_port = newfwd->listen_port;
fwd->listen_path = newfwd->listen_path;
fwd->connect_host = newfwd->connect_host;
fwd->connect_port = newfwd->connect_port;
fwd->connect_path = newfwd->connect_path;
fwd->handle = newfwd->handle;
fwd->allocated_port = 0;
}
@ -321,7 +330,9 @@ clear_forwardings(Options *options)
for (i = 0; i < options->num_local_forwards; i++) {
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_path);
}
if (options->num_local_forwards > 0) {
free(options->local_forwards);
@ -330,7 +341,9 @@ clear_forwardings(Options *options)
options->num_local_forwards = 0;
for (i = 0; i < options->num_remote_forwards; i++) {
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_path);
}
if (options->num_remote_forwards > 0) {
free(options->remote_forwards);
@ -715,7 +728,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host,
LogLevel *log_level_ptr;
long long val64;
size_t len;
Forward fwd;
struct Forward fwd;
const struct multistate *multistate_ptr;
struct allowed_cname *cname;
@ -805,7 +818,7 @@ parse_time:
goto parse_time;
case oGatewayPorts:
intptr = &options->gateway_ports;
intptr = &options->fwd_opts.gateway_ports;
goto parse_flag;
case oExitOnForwardFailure:
@ -1405,6 +1418,21 @@ parse_int:
intptr = &options->canonicalize_fallback_local;
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:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
@ -1502,7 +1530,9 @@ initialize_options(Options * options)
options->forward_x11_timeout = -1;
options->exit_on_forward_failure = -1;
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->rsa_authentication = -1;
options->pubkey_authentication = -1;
@ -1615,8 +1645,12 @@ fill_default_options(Options * options)
options->exit_on_forward_failure = 0;
if (options->xauth_location == NULL)
options->xauth_location = _PATH_XAUTH;
if (options->gateway_ports == -1)
options->gateway_ports = 0;
if (options->fwd_opts.gateway_ports == -1)
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)
options->use_privileged_port = 0;
if (options->rsa_authentication == -1)
@ -1768,22 +1802,92 @@ fill_default_options(Options * options)
/* 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
* parses a string containing a port forwarding specification of the form:
* dynamicfwd == 0
* [listenhost:]listenport:connecthost:connectport
* [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
* listenpath:connectpath
* dynamicfwd == 1
* [listenhost:]listenport
* returns number of arguments parsed or zero on error
*/
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;
char *p, *cp, *fwdarg[4];
memset(fwd, '\0', sizeof(*fwd));
memset(fwd, 0, sizeof(*fwd));
memset(fwdargs, 0, sizeof(fwdargs));
cp = p = xstrdup(fwdspec);
@ -1791,39 +1895,70 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
while (isspace((u_char)*cp))
cp++;
for (i = 0; i < 4; ++i)
if ((fwdarg[i] = hpdelim(&cp)) == NULL)
for (i = 0; i < 4; ++i) {
if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
break;
}
/* Check for trailing garbage */
if (cp != NULL)
if (cp != NULL && *cp != '\0') {
i = 0; /* failure */
}
switch (i) {
case 1:
fwd->listen_host = NULL;
fwd->listen_port = a2port(fwdarg[0]);
if (fwdargs[0].ispath) {
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");
break;
case 2:
fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
fwd->listen_port = a2port(fwdarg[1]);
fwd->connect_host = xstrdup("socks");
if (fwdargs[0].ispath && fwdargs[1].ispath) {
fwd->listen_path = xstrdup(fwdargs[0].arg);
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;
case 3:
fwd->listen_host = NULL;
fwd->listen_port = a2port(fwdarg[0]);
fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
fwd->connect_port = a2port(fwdarg[2]);
if (fwdargs[0].ispath) {
fwd->listen_path = xstrdup(fwdargs[0].arg);
fwd->listen_port = PORT_STREAMLOCAL;
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;
case 4:
fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
fwd->listen_port = a2port(fwdarg[1]);
fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
fwd->connect_port = a2port(fwdarg[3]);
fwd->listen_host = xstrdup(fwdargs[0].arg);
fwd->listen_port = a2port(fwdargs[1].arg);
fwd->connect_host = xstrdup(fwdargs[2].arg);
fwd->connect_port = a2port(fwdargs[3].arg);
break;
default:
i = 0; /* failure */
@ -1835,29 +1970,42 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
if (!(i == 1 || i == 2))
goto fail_free;
} else {
if (!(i == 3 || i == 4))
goto fail_free;
if (fwd->connect_port <= 0)
if (!(i == 3 || i == 4)) {
if (fwd->connect_path == NULL &&
fwd->listen_path == NULL)
goto fail_free;
}
if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
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;
if (fwd->connect_host != NULL &&
strlen(fwd->connect_host) >= NI_MAXHOST)
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 &&
strlen(fwd->listen_host) >= NI_MAXHOST)
goto fail_free;
if (fwd->listen_path != NULL &&
strlen(fwd->listen_path) >= PATH_MAX_SUN)
goto fail_free;
return (i);
fail_free:
free(fwd->connect_host);
fwd->connect_host = NULL;
free(fwd->connect_path);
fwd->connect_path = NULL;
free(fwd->listen_host);
fwd->listen_host = NULL;
free(fwd->listen_path);
fwd->listen_path = NULL;
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>
@ -16,21 +16,12 @@
#ifndef 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. */
#define MAX_SEND_ENV 256
#define SSH_MAX_HOSTS_FILES 32
#define MAX_CANON_DOMAINS 32
#define PATH_MAX_SUN (sizeof((struct sockaddr_un *)0)->sun_path)
struct allowed_cname {
char *source_list;
@ -44,7 +35,7 @@ typedef struct {
int forward_x11_trusted; /* Trust Forward X11 display. */
int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */
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 rhosts_rsa_authentication; /* Try rhosts with RSA
* authentication. */
@ -106,11 +97,11 @@ typedef struct {
/* Local TCP/IP forward requests. */
int num_local_forwards;
Forward *local_forwards;
struct Forward *local_forwards;
/* Remote TCP/IP forward requests. */
int num_remote_forwards;
Forward *remote_forwards;
struct Forward *remote_forwards;
int clear_forwardings;
int enable_ssh_keysign;
@ -181,12 +172,12 @@ int process_config_line(Options *, struct passwd *, const char *, char *,
const char *, int, int *, int);
int read_config_file(const char *, struct passwd *, const char *,
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 option_clear_or_none(const char *);
void add_local_forward(Options *, const Forward *);
void add_remote_forward(Options *, const Forward *);
void add_local_forward(Options *, const struct Forward *);
void add_remote_forward(Options *, const struct Forward *);
void add_identity_file(Options *, const char *, const char *, int);
#endif /* READCONF_H */

View File

@ -60,7 +60,7 @@ static const struct sandbox_policy preauth_policy[] = {
{ SYS___sysctl, SYSTR_POLICY_PERMIT },
#endif
{ SYS_sendsyslog, SYSTR_POLICY_PERMIT },
// { SYS_sendsyslog, SYSTR_POLICY_PERMIT },
{ SYS_close, SYSTR_POLICY_PERMIT },
{ SYS_exit, 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
* All rights reserved
@ -39,10 +39,10 @@
#include "ssh.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "pathnames.h"
#include "misc.h"
#include "cipher.h"
#include "key.h"
#include "kex.h"
@ -120,6 +120,7 @@ initialize_server_options(ServerOptions *options)
options->rekey_limit = -1;
options->rekey_interval = -1;
options->allow_tcp_forwarding = -1;
options->allow_streamlocal_forwarding = -1;
options->allow_agent_forwarding = -1;
options->num_allow_users = 0;
options->num_deny_users = 0;
@ -129,7 +130,9 @@ initialize_server_options(ServerOptions *options)
options->macs = NULL;
options->kex_algorithms = NULL;
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->max_startups_begin = -1;
options->max_startups_rate = -1;
@ -269,10 +272,12 @@ fill_default_server_options(ServerOptions *options)
options->rekey_interval = 0;
if (options->allow_tcp_forwarding == -1)
options->allow_tcp_forwarding = FORWARD_ALLOW;
if (options->allow_streamlocal_forwarding == -1)
options->allow_streamlocal_forwarding = FORWARD_ALLOW;
if (options->allow_agent_forwarding == -1)
options->allow_agent_forwarding = 1;
if (options->gateway_ports == -1)
options->gateway_ports = 0;
if (options->fwd_opts.gateway_ports == -1)
options->fwd_opts.gateway_ports = 0;
if (options->max_startups == -1)
options->max_startups = 100;
if (options->max_startups_rate == -1)
@ -303,6 +308,10 @@ fill_default_server_options(ServerOptions *options)
options->ip_qos_bulk = IPTOS_THROUGHPUT;
if (options->version_addendum == NULL)
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 */
if (use_privsep == -1)
use_privsep = PRIVSEP_NOSANDBOX;
@ -351,6 +360,8 @@ typedef enum {
sKexAlgorithms, sIPQoS, sVersionAddendum,
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
sStreamLocalBindMask, sStreamLocalBindUnlink,
sAllowStreamLocalForwarding,
sDeprecated, sUnsupported
} ServerOpCodes;
@ -478,6 +489,9 @@ static struct {
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
{ "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
{ NULL, sBadOption, 0 }
};
@ -1195,7 +1209,7 @@ process_server_config_line(ServerOptions *options, char *line,
break;
case sGatewayPorts:
intptr = &options->gateway_ports;
intptr = &options->fwd_opts.gateway_ports;
multistate_ptr = multistate_gatewayports;
goto parse_multistate;
@ -1230,6 +1244,11 @@ process_server_config_line(ServerOptions *options, char *line,
multistate_ptr = multistate_tcpfwd;
goto parse_multistate;
case sAllowStreamLocalForwarding:
intptr = &options->allow_streamlocal_forwarding;
multistate_ptr = multistate_tcpfwd;
goto parse_multistate;
case sAllowAgentForwarding:
intptr = &options->allow_agent_forwarding;
goto parse_flag;
@ -1628,6 +1647,22 @@ process_server_config_line(ServerOptions *options, char *line,
}
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:
logit("%s line %d: Deprecated option %s",
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(allow_tcp_forwarding);
M_CP_INTOPT(allow_streamlocal_forwarding);
M_CP_INTOPT(allow_agent_forwarding);
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_forwarding);
M_CP_INTOPT(x11_use_localhost);
@ -1867,6 +1903,8 @@ fmt_intarg(ServerOpCodes code, int val)
return fmt_multistate_int(val, multistate_privsep);
case sAllowTcpForwarding:
return fmt_multistate_int(val, multistate_tcpfwd);
case sAllowStreamLocalForwarding:
return fmt_multistate_int(val, multistate_tcpfwd);
case sProtocol:
switch (val) {
case SSH_PROTO_1:
@ -2023,9 +2061,10 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
dump_cfg_fmtint(sUseLogin, o->use_login);
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(sAllowTcpForwarding, o->allow_tcp_forwarding);
dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
/* 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>
@ -92,7 +92,7 @@ typedef struct {
char *macs; /* Supported SSH2 macs. */
char *kex_algorithms; /* SSH2 kex methods in order of preference. */
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. */
LogLevel log_level; /* Level for system logging. */
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 compression; /* If true, compression is allowed */
int allow_tcp_forwarding; /* One of FORWARD_* */
int allow_streamlocal_forwarding; /* One of FORWARD_* */
int allow_agent_forwarding;
u_int num_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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -61,6 +61,7 @@
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "canohost.h"
#include "sshpty.h"
@ -77,7 +78,6 @@
#include "dispatch.h"
#include "auth-options.h"
#include "serverloop.h"
#include "misc.h"
#include "roaming.h"
extern ServerOptions options;
@ -970,7 +970,7 @@ server_request_direct_tcpip(void)
/* XXX fine grained permissions */
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
!no_port_forwarding_flag) {
c = channel_connect_to(target, target_port,
c = channel_connect_to_port(target, target_port,
"direct-tcpip", "direct-tcpip");
} else {
logit("refused local port forward: "
@ -984,6 +984,38 @@ server_request_direct_tcpip(void)
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 *
server_request_tun(void)
{
@ -1081,6 +1113,8 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
c = server_request_session();
} else if (strcmp(ctype, "direct-tcpip") == 0) {
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) {
c = server_request_tun();
}
@ -1125,47 +1159,74 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
/* -R style forwarding */
if (strcmp(rtype, "tcpip-forward") == 0) {
struct passwd *pw;
char *listen_address;
u_short listen_port;
struct Forward fwd;
pw = the_authctxt->pw;
if (pw == NULL || !the_authctxt->valid)
fatal("server_input_global_request: no/invalid user");
listen_address = packet_get_string(NULL);
listen_port = (u_short)packet_get_int();
memset(&fwd, 0, sizeof(fwd));
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",
listen_address, listen_port);
fwd.listen_host, fwd.listen_port);
/* check permissions */
if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
no_port_forwarding_flag ||
(!want_reply && listen_port == 0)
(!want_reply && fwd.listen_port == 0) ||
#ifndef NO_IPPORT_RESERVED_CONCEPT
|| (listen_port != 0 && listen_port < IPPORT_RESERVED &&
pw->pw_uid != 0)
(fwd.listen_port != 0 && fwd.listen_port < IPPORT_RESERVED &&
pw->pw_uid != 0)
#endif
) {
success = 0;
packet_send_debug("Server has disabled port forwarding.");
} else {
/* Start listening on the port */
success = channel_setup_remote_fwd_listener(
listen_address, listen_port,
&allocated_listen_port, options.gateway_ports);
success = channel_setup_remote_fwd_listener(&fwd,
&allocated_listen_port, &options.fwd_opts);
}
free(listen_address);
free(fwd.listen_host);
} else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
char *cancel_address;
u_short cancel_port;
struct Forward fwd;
cancel_address = packet_get_string(NULL);
cancel_port = (u_short)packet_get_int();
memset(&fwd, 0, sizeof(fwd));
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__,
cancel_address, cancel_port);
fwd.listen_host, fwd.listen_port);
success = channel_cancel_rport_listener(cancel_address,
cancel_port);
free(cancel_address);
success = channel_cancel_rport_listener(&fwd);
free(fwd.listen_host);
} 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) {
no_more_sessions = 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
* All rights reserved
@ -84,11 +84,11 @@
#include "authfd.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "sshlogin.h"
#include "serverloop.h"
#include "canohost.h"
#include "misc.h"
#include "session.h"
#include "kex.h"
#include "monitor_wrap.h"
@ -183,7 +183,6 @@ auth_input_request_forwarding(struct passwd * pw)
{
Channel *nc;
int sock = -1;
struct sockaddr_un sunaddr;
if (auth_sock_name != NULL) {
error("authentication forwarding requested twice.");
@ -209,33 +208,15 @@ auth_input_request_forwarding(struct passwd * pw)
xasprintf(&auth_sock_name, "%s/agent.%ld",
auth_sock_dir, (long) getpid());
/* Create the socket. */
sock = socket(AF_UNIX, SOCK_STREAM, 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;
}
/* Start a Unix listener on auth_sock_name. */
sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0);
/* Restore the privileged uid. */
restore_uid();
/* Start listening on the socket. */
if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
error("listen: %.100s", strerror(errno));
/* Check for socket/bind/listen failure. */
if (sock < 0)
goto authsock_err;
}
/* Allocate a channel for the authentication agent socket. */
nc = channel_new("auth socket",
@ -274,6 +255,7 @@ do_authenticated(Authctxt *authctxt)
setproctitle("%s", authctxt->pw->pw_name);
/* setup the channel layer */
/* XXX - streamlocal? */
if (no_port_forwarding_flag ||
(options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
channel_disable_adm_local_opens();
@ -393,7 +375,7 @@ do_authenticated1(Authctxt *authctxt)
}
debug("Received TCP/IP port forwarding request.");
if (channel_input_port_forward_request(s->pw->pw_uid == 0,
options.gateway_ports) < 0) {
&options.fwd_opts) < 0) {
debug("Port forwarding failed.");
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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -1038,11 +1038,9 @@ main(int ac, char **av)
u_int nalloc;
char *shell, *format, *pidstr, *agentsocket = NULL;
fd_set *readsetp = NULL, *writesetp = NULL;
struct sockaddr_un sunaddr;
#ifdef HAVE_SETRLIMIT
struct rlimit rlim;
#endif
int prev_mask;
extern int optind;
extern char *optarg;
pid_t pid;
@ -1161,27 +1159,12 @@ main(int ac, char **av)
* Create socket early so it will exist before command gets run from
* the parent.
*/
sock = socket(AF_UNIX, SOCK_STREAM, 0);
sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0);
if (sock < 0) {
perror("socket");
/* XXX - unix_listener() calls error() not perror() */
*socket_name = '\0'; /* Don't unlink any existing file */
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

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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -96,9 +96,9 @@
#include "dispatch.h"
#include "clientloop.h"
#include "log.h"
#include "misc.h"
#include "readconf.h"
#include "sshconnect.h"
#include "misc.h"
#include "kex.h"
#include "mac.h"
#include "sshpty.h"
@ -423,7 +423,7 @@ main(int ac, char **av)
int timeout_ms;
extern int optind, optreset;
extern char *optarg;
Forward fwd;
struct Forward fwd;
struct addrinfo *addrs = NULL;
struct ssh_digest_ctx *md;
u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
@ -545,7 +545,7 @@ main(int ac, char **av)
options.forward_x11_trusted = 1;
break;
case 'g':
options.gateway_ports = 1;
options.fwd_opts.gateway_ports = 1;
break;
case 'O':
if (stdio_forward_host != NULL)
@ -1305,15 +1305,17 @@ fork_postauth(void)
static void
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? */
debug("remote forward %s for: listen %s%s%d, connect %s:%d",
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
rfwd->listen_host == NULL ? "" : rfwd->listen_host,
rfwd->listen_host == NULL ? "" : ":",
rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
if (rfwd->listen_port == 0) {
rfwd->listen_path ? rfwd->listen_path :
rfwd->listen_host ? rfwd->listen_host : "",
(rfwd->listen_path || rfwd->listen_host) ? ":" : "",
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) {
rfwd->allocated_port = packet_get_int();
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 (options.exit_on_forward_failure)
fatal("Error: remote port forwarding failed for "
"listen port %d", rfwd->listen_port);
else
logit("Warning: remote port forwarding failed for "
"listen port %d", rfwd->listen_port);
if (options.exit_on_forward_failure) {
if (rfwd->listen_path != NULL)
fatal("Error: remote port forwarding failed "
"for listen path %s", rfwd->listen_path);
else
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) {
debug("All remote forwarding requests processed");
@ -1380,18 +1391,18 @@ ssh_init_forwarding(void)
for (i = 0; i < options.num_local_forwards; i++) {
debug("Local connections to %.200s:%d forwarded to remote "
"address %.200s:%d",
(options.local_forwards[i].listen_path != NULL) ?
options.local_forwards[i].listen_path :
(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_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_port);
success += channel_setup_local_fwd_listener(
options.local_forwards[i].listen_host,
options.local_forwards[i].listen_port,
options.local_forwards[i].connect_host,
options.local_forwards[i].connect_port,
options.gateway_ports);
&options.local_forwards[i], &options.fwd_opts);
}
if (i > 0 && success != i && options.exit_on_forward_failure)
fatal("Could not request local forwarding.");
@ -1402,17 +1413,18 @@ ssh_init_forwarding(void)
for (i = 0; i < options.num_remote_forwards; i++) {
debug("Remote connections from %.200s:%d forwarded to "
"local address %.200s:%d",
(options.remote_forwards[i].listen_path != NULL) ?
options.remote_forwards[i].listen_path :
(options.remote_forwards[i].listen_host == NULL) ?
"LOCALHOST" : options.remote_forwards[i].listen_host,
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_port);
options.remote_forwards[i].handle =
channel_request_remote_forwarding(
options.remote_forwards[i].listen_host,
options.remote_forwards[i].listen_port,
options.remote_forwards[i].connect_host,
options.remote_forwards[i].connect_port);
&options.remote_forwards[i]);
if (options.remote_forwards[i].handle < 0) {
if (options.exit_on_forward_failure)
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
.\" 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 $
.Dd $Mdocdate: July 7 2014 $
.\" $OpenBSD: ssh_config.5,v 1.191 2014/07/15 15:54:14 millert Exp $
.Dd $Mdocdate: July 15 2014 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
@ -1303,6 +1303,33 @@ channel to request a response from the server.
The default
is 0, indicating that these messages will not be sent to the server.
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
If this flag is set to
.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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -54,9 +54,9 @@
#include "sshconnect.h"
#include "hostfile.h"
#include "log.h"
#include "misc.h"
#include "readconf.h"
#include "atomicio.h"
#include "misc.h"
#include "dns.h"
#include "roaming.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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -38,11 +38,11 @@
#include "kex.h"
#include "uidswap.h"
#include "log.h"
#include "misc.h"
#include "readconf.h"
#include "authfd.h"
#include "sshconnect.h"
#include "authfile.h"
#include "misc.h"
#include "canohost.h"
#include "hostfile.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) 2008 Damien Miller. All rights reserved.
@ -61,8 +61,8 @@
#include "dh.h"
#include "authfd.h"
#include "log.h"
#include "readconf.h"
#include "misc.h"
#include "readconf.h"
#include "match.h"
#include "dispatch.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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -93,6 +93,7 @@
#include "packet.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "uidswap.h"
#include "compat.h"
@ -108,7 +109,6 @@
#include "hostfile.h"
#include "auth.h"
#include "authfd.h"
#include "misc.h"
#include "msg.h"
#include "dispatch.h"
#include "channels.h"

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" 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 $
.Dd $Mdocdate: July 3 2014 $
.\" $OpenBSD: sshd_config.5,v 1.175 2014/07/15 15:54:14 millert Exp $
.Dd $Mdocdate: July 15 2014 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
@ -140,6 +140,26 @@ The default is
Note that disabling TCP forwarding does not improve security unless
users are also denied shell access, as they can always install their
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
This keyword can be followed by a list of user name patterns, separated
by spaces.
@ -1171,6 +1191,33 @@ This option applies to protocol version 1 only.
.It Cm ServerKeyBits
Defines the number of bits in the ephemeral protocol version 1 server key.
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
Specifies whether
.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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -58,6 +58,7 @@
#include "loginrec.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
extern Buffer loginmsg;