mirror of
git://anongit.mindrot.org/openssh.git
synced 2024-11-23 09:17:32 +08:00
- 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@
This commit is contained in:
parent
6262d760e0
commit
7acefbbcbe
17
ChangeLog
17
ChangeLog
@ -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.
|
||||
|
52
PROTOCOL
52
PROTOCOL
@ -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 $
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
@ -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 "
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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
4
auth.c
@ -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
|
||||
|
3
auth1.c
3
auth1.c
@ -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"
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "packet.h"
|
||||
#include "dispatch.h"
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
#include "servconf.h"
|
||||
|
||||
/* import */
|
||||
|
@ -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"
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
||||
|
3
auth2.c
3
auth2.c
@ -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"
|
||||
|
12
canohost.c
12
canohost.c
@ -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)
|
||||
|
602
channels.c
602
channels.c
@ -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)
|
||||
{
|
||||
|
28
channels.h
28
channels.h
@ -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 */
|
||||
|
78
clientloop.c
78
clientloop.c
@ -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
49
misc.c
@ -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
25
misc.h
@ -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)));
|
||||
|
@ -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
203
mux.c
@ -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)
|
||||
|
4
packet.c
4
packet.c
@ -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"
|
||||
|
@ -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"
|
||||
|
224
readconf.c
224
readconf.c
@ -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);
|
||||
}
|
||||
|
25
readconf.h
25
readconf.h
@ -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 */
|
||||
|
@ -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 },
|
||||
|
55
servconf.c
55
servconf.c
@ -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 */
|
||||
|
@ -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];
|
||||
|
107
serverloop.c
107
serverloop.c
@ -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;
|
||||
|
34
session.c
34
session.c
@ -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;
|
||||
}
|
||||
|
23
ssh-agent.c
23
ssh-agent.c
@ -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
62
ssh.c
@ -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.");
|
||||
|
31
ssh_config.5
31
ssh_config.5
@ -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 ,
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
4
sshd.c
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user