- 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
|
20140717
|
||||||
- (djm) [digest-openssl.c] Preserve array order when disabling digests.
|
- (djm) [digest-openssl.c] Preserve array order when disabling digests.
|
||||||
Reported by Petr Lautrbach.
|
Reported by Petr Lautrbach.
|
||||||
|
|
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
|
The "frame" field contains an IEEE 802.3 Ethernet frame, including
|
||||||
header.
|
header.
|
||||||
|
|
||||||
|
2.4. connection: Unix domain socket forwarding
|
||||||
|
|
||||||
|
OpenSSH supports local and remote Unix domain socket forwarding
|
||||||
|
using the "streamlocal" extension. Forwarding is initiated as per
|
||||||
|
TCP sockets but with a single path instead of a host and port.
|
||||||
|
|
||||||
|
Similar to direct-tcpip, direct-streamlocal is sent by the client
|
||||||
|
to request that the server make a connection to a Unix domain socket.
|
||||||
|
|
||||||
|
byte SSH_MSG_CHANNEL_OPEN
|
||||||
|
string "direct-streamlocal@openssh.com"
|
||||||
|
uint32 sender channel
|
||||||
|
uint32 initial window size
|
||||||
|
uint32 maximum packet size
|
||||||
|
string socket path
|
||||||
|
string reserved for future use
|
||||||
|
|
||||||
|
Similar to forwarded-tcpip, forwarded-streamlocal is sent by the
|
||||||
|
server when the client has previously send the server a streamlocal-forward
|
||||||
|
GLOBAL_REQUEST.
|
||||||
|
|
||||||
|
byte SSH_MSG_CHANNEL_OPEN
|
||||||
|
string "forwarded-streamlocal@openssh.com"
|
||||||
|
uint32 sender channel
|
||||||
|
uint32 initial window size
|
||||||
|
uint32 maximum packet size
|
||||||
|
string socket path
|
||||||
|
string reserved for future use
|
||||||
|
|
||||||
|
The reserved field is not currently defined and is ignored on the
|
||||||
|
remote end. It is intended to be used in the future to pass
|
||||||
|
information about the socket file, such as ownership and mode.
|
||||||
|
The client currently sends the empty string for this field.
|
||||||
|
|
||||||
|
Similar to tcpip-forward, streamlocal-forward is sent by the client
|
||||||
|
to request remote forwarding of a Unix domain socket.
|
||||||
|
|
||||||
|
byte SSH2_MSG_GLOBAL_REQUEST
|
||||||
|
string "streamlocal-forward@openssh.com"
|
||||||
|
boolean TRUE
|
||||||
|
string socket path
|
||||||
|
|
||||||
|
Similar to cancel-tcpip-forward, cancel-streamlocal-forward is sent
|
||||||
|
by the client cancel the forwarding of a Unix domain socket.
|
||||||
|
|
||||||
|
byte SSH2_MSG_GLOBAL_REQUEST
|
||||||
|
string "cancel-streamlocal-forward@openssh.com"
|
||||||
|
boolean FALSE
|
||||||
|
string socket path
|
||||||
|
|
||||||
3. SFTP protocol changes
|
3. SFTP protocol changes
|
||||||
|
|
||||||
3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK
|
3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK
|
||||||
|
@ -356,4 +406,4 @@ respond with a SSH_FXP_STATUS message.
|
||||||
This extension is advertised in the SSH_FXP_VERSION hello with version
|
This extension is advertised in the SSH_FXP_VERSION hello with version
|
||||||
"1".
|
"1".
|
||||||
|
|
||||||
$OpenBSD: PROTOCOL,v 1.23 2013/12/01 23:19:05 djm Exp $
|
$OpenBSD: PROTOCOL,v 1.24 2014/07/15 15:54:14 millert Exp $
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
|
|
||||||
/* limited protocol v1 interface to kbd-interactive authentication */
|
/* limited protocol v1 interface to kbd-interactive authentication */
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: auth-options.c,v 1.63 2014/06/24 01:13:21 djm Exp $ */
|
/* $OpenBSD: auth-options.c,v 1.64 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -26,9 +26,9 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "canohost.h"
|
#include "canohost.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "channels.h"
|
#include "channels.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "auth-options.h"
|
#include "auth-options.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
|
@ -325,6 +325,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
|
||||||
patterns[i] = '\0';
|
patterns[i] = '\0';
|
||||||
opts++;
|
opts++;
|
||||||
p = patterns;
|
p = patterns;
|
||||||
|
/* XXX - add streamlocal support */
|
||||||
host = hpdelim(&p);
|
host = hpdelim(&p);
|
||||||
if (host == NULL || strlen(host) >= NI_MAXHOST) {
|
if (host == NULL || strlen(host) >= NI_MAXHOST) {
|
||||||
debug("%.100s, line %lu: Bad permitopen "
|
debug("%.100s, line %lu: Bad permitopen "
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: auth-passwd.c,v 1.43 2007/09/21 08:15:29 djm Exp $ */
|
/* $OpenBSD: auth-passwd.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -48,6 +48,7 @@
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: auth-rh-rsa.c,v 1.43 2010/03/04 10:36:03 djm Exp $ */
|
/* $OpenBSD: auth-rh-rsa.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: auth-rhosts.c,v 1.44 2010/03/07 11:57:13 dtucker Exp $ */
|
/* $OpenBSD: auth-rhosts.c,v 1.45 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -34,12 +34,12 @@
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "canohost.h"
|
#include "canohost.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "misc.h"
|
|
||||||
|
|
||||||
/* import */
|
/* import */
|
||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: auth-rsa.c,v 1.87 2014/06/24 01:13:21 djm Exp $ */
|
/* $OpenBSD: auth-rsa.c,v 1.88 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -35,6 +35,7 @@
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "auth-options.h"
|
#include "auth-options.h"
|
||||||
|
@ -45,7 +46,6 @@
|
||||||
#endif
|
#endif
|
||||||
#include "monitor_wrap.h"
|
#include "monitor_wrap.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "misc.h"
|
|
||||||
|
|
||||||
#include "digest.h"
|
#include "digest.h"
|
||||||
|
|
||||||
|
|
4
auth.c
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.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -56,6 +56,7 @@
|
||||||
#include "groupaccess.h"
|
#include "groupaccess.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
|
@ -63,7 +64,6 @@
|
||||||
#include "auth-options.h"
|
#include "auth-options.h"
|
||||||
#include "canohost.h"
|
#include "canohost.h"
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "loginrec.h"
|
#include "loginrec.h"
|
||||||
#ifdef GSSAPI
|
#ifdef GSSAPI
|
||||||
|
|
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
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "dispatch.h"
|
#include "dispatch.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
|
|
||||||
/* import */
|
/* import */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: auth2-hostbased.c,v 1.17 2013/12/30 23:52:27 djm Exp $ */
|
/* $OpenBSD: auth2-hostbased.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -36,6 +36,7 @@
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: auth2-kbdint.c,v 1.6 2013/05/17 00:13:13 djm Exp $ */
|
/* $OpenBSD: auth2-kbdint.c,v 1.7 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -36,6 +36,7 @@
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
|
|
||||||
/* import */
|
/* import */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: auth2-none.c,v 1.17 2014/06/24 01:13:21 djm Exp $ */
|
/* $OpenBSD: auth2-none.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -43,6 +43,7 @@
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "ssh2.h"
|
#include "ssh2.h"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: auth2-passwd.c,v 1.11 2014/02/02 03:44:31 djm Exp $ */
|
/* $OpenBSD: auth2-passwd.c,v 1.12 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -41,6 +41,7 @@
|
||||||
#include "ssh-gss.h"
|
#include "ssh-gss.h"
|
||||||
#endif
|
#endif
|
||||||
#include "monitor_wrap.h"
|
#include "monitor_wrap.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
|
|
||||||
/* import */
|
/* import */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: auth2-pubkey.c,v 1.40 2014/06/24 01:13:21 djm Exp $ */
|
/* $OpenBSD: auth2-pubkey.c,v 1.41 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -48,6 +48,7 @@
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
@ -61,7 +62,6 @@
|
||||||
#include "ssh-gss.h"
|
#include "ssh-gss.h"
|
||||||
#endif
|
#endif
|
||||||
#include "monitor_wrap.h"
|
#include "monitor_wrap.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "authfile.h"
|
#include "authfile.h"
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
|
|
||||||
|
|
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.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -41,6 +41,7 @@
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
@ -262,6 +263,11 @@ get_socket_address(int sock, int remote, int flags)
|
||||||
if (addr.ss_family == AF_INET6)
|
if (addr.ss_family == AF_INET6)
|
||||||
addrlen = sizeof(struct sockaddr_in6);
|
addrlen = sizeof(struct sockaddr_in6);
|
||||||
|
|
||||||
|
if (addr.ss_family == AF_UNIX) {
|
||||||
|
/* Get the Unix domain socket path. */
|
||||||
|
return xstrdup(((struct sockaddr_un *)&addr)->sun_path);
|
||||||
|
}
|
||||||
|
|
||||||
ipv64_normalise_mapped(&addr, &addrlen);
|
ipv64_normalise_mapped(&addr, &addrlen);
|
||||||
|
|
||||||
/* Get the address in ascii. */
|
/* Get the address in ascii. */
|
||||||
|
@ -384,6 +390,10 @@ get_sock_port(int sock, int local)
|
||||||
if (from.ss_family == AF_INET6)
|
if (from.ss_family == AF_INET6)
|
||||||
fromlen = sizeof(struct sockaddr_in6);
|
fromlen = sizeof(struct sockaddr_in6);
|
||||||
|
|
||||||
|
/* Unix domain sockets don't have a port number. */
|
||||||
|
if (from.ss_family == AF_UNIX)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Return port number. */
|
/* Return port number. */
|
||||||
if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
|
if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
|
||||||
strport, sizeof(strport), NI_NUMERICSERV)) != 0)
|
strport, sizeof(strport), NI_NUMERICSERV)) != 0)
|
||||||
|
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -42,6 +42,7 @@
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
@ -107,11 +108,15 @@ static int channel_max_fd = 0;
|
||||||
* a corrupt remote server from accessing arbitrary TCP/IP ports on our local
|
* a corrupt remote server from accessing arbitrary TCP/IP ports on our local
|
||||||
* network (which might be behind a firewall).
|
* network (which might be behind a firewall).
|
||||||
*/
|
*/
|
||||||
|
/* XXX: streamlocal wants a path instead of host:port */
|
||||||
|
/* Overload host_to_connect; we could just make this match Forward */
|
||||||
|
/* XXX - can we use listen_host instead of listen_path? */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *host_to_connect; /* Connect to 'host'. */
|
char *host_to_connect; /* Connect to 'host'. */
|
||||||
u_short port_to_connect; /* Connect to 'port'. */
|
int port_to_connect; /* Connect to 'port'. */
|
||||||
char *listen_host; /* Remote side should listen address. */
|
char *listen_host; /* Remote side should listen address. */
|
||||||
u_short listen_port; /* Remote side should listen port. */
|
char *listen_path; /* Remote side should listen path. */
|
||||||
|
int listen_port; /* Remote side should listen port. */
|
||||||
} ForwardPermission;
|
} ForwardPermission;
|
||||||
|
|
||||||
/* List of all permitted host/port pairs to connect by the user. */
|
/* List of all permitted host/port pairs to connect by the user. */
|
||||||
|
@ -474,6 +479,8 @@ channel_stop_listening(void)
|
||||||
case SSH_CHANNEL_PORT_LISTENER:
|
case SSH_CHANNEL_PORT_LISTENER:
|
||||||
case SSH_CHANNEL_RPORT_LISTENER:
|
case SSH_CHANNEL_RPORT_LISTENER:
|
||||||
case SSH_CHANNEL_X11_LISTENER:
|
case SSH_CHANNEL_X11_LISTENER:
|
||||||
|
case SSH_CHANNEL_UNIX_LISTENER:
|
||||||
|
case SSH_CHANNEL_RUNIX_LISTENER:
|
||||||
channel_close_fd(&c->sock);
|
channel_close_fd(&c->sock);
|
||||||
channel_free(c);
|
channel_free(c);
|
||||||
break;
|
break;
|
||||||
|
@ -536,6 +543,8 @@ channel_still_open(void)
|
||||||
case SSH_CHANNEL_CONNECTING:
|
case SSH_CHANNEL_CONNECTING:
|
||||||
case SSH_CHANNEL_ZOMBIE:
|
case SSH_CHANNEL_ZOMBIE:
|
||||||
case SSH_CHANNEL_ABANDONED:
|
case SSH_CHANNEL_ABANDONED:
|
||||||
|
case SSH_CHANNEL_UNIX_LISTENER:
|
||||||
|
case SSH_CHANNEL_RUNIX_LISTENER:
|
||||||
continue;
|
continue;
|
||||||
case SSH_CHANNEL_LARVAL:
|
case SSH_CHANNEL_LARVAL:
|
||||||
if (!compat20)
|
if (!compat20)
|
||||||
|
@ -582,6 +591,8 @@ channel_find_open(void)
|
||||||
case SSH_CHANNEL_CONNECTING:
|
case SSH_CHANNEL_CONNECTING:
|
||||||
case SSH_CHANNEL_ZOMBIE:
|
case SSH_CHANNEL_ZOMBIE:
|
||||||
case SSH_CHANNEL_ABANDONED:
|
case SSH_CHANNEL_ABANDONED:
|
||||||
|
case SSH_CHANNEL_UNIX_LISTENER:
|
||||||
|
case SSH_CHANNEL_RUNIX_LISTENER:
|
||||||
continue;
|
continue;
|
||||||
case SSH_CHANNEL_LARVAL:
|
case SSH_CHANNEL_LARVAL:
|
||||||
case SSH_CHANNEL_AUTH_SOCKET:
|
case SSH_CHANNEL_AUTH_SOCKET:
|
||||||
|
@ -632,6 +643,8 @@ channel_open_message(void)
|
||||||
case SSH_CHANNEL_ABANDONED:
|
case SSH_CHANNEL_ABANDONED:
|
||||||
case SSH_CHANNEL_MUX_CLIENT:
|
case SSH_CHANNEL_MUX_CLIENT:
|
||||||
case SSH_CHANNEL_MUX_LISTENER:
|
case SSH_CHANNEL_MUX_LISTENER:
|
||||||
|
case SSH_CHANNEL_UNIX_LISTENER:
|
||||||
|
case SSH_CHANNEL_RUNIX_LISTENER:
|
||||||
continue;
|
continue;
|
||||||
case SSH_CHANNEL_LARVAL:
|
case SSH_CHANNEL_LARVAL:
|
||||||
case SSH_CHANNEL_OPENING:
|
case SSH_CHANNEL_OPENING:
|
||||||
|
@ -1387,7 +1400,6 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
||||||
static void
|
static void
|
||||||
port_open_helper(Channel *c, char *rtype)
|
port_open_helper(Channel *c, char *rtype)
|
||||||
{
|
{
|
||||||
int direct;
|
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *local_ipaddr = get_local_ipaddr(c->sock);
|
char *local_ipaddr = get_local_ipaddr(c->sock);
|
||||||
int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1);
|
int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1);
|
||||||
|
@ -1401,8 +1413,6 @@ port_open_helper(Channel *c, char *rtype)
|
||||||
remote_port = 65535;
|
remote_port = 65535;
|
||||||
}
|
}
|
||||||
|
|
||||||
direct = (strcmp(rtype, "direct-tcpip") == 0);
|
|
||||||
|
|
||||||
snprintf(buf, sizeof buf,
|
snprintf(buf, sizeof buf,
|
||||||
"%s: listening port %d for %.100s port %d, "
|
"%s: listening port %d for %.100s port %d, "
|
||||||
"connect from %.200s port %d to %.100s port %d",
|
"connect from %.200s port %d to %.100s port %d",
|
||||||
|
@ -1418,18 +1428,29 @@ port_open_helper(Channel *c, char *rtype)
|
||||||
packet_put_int(c->self);
|
packet_put_int(c->self);
|
||||||
packet_put_int(c->local_window_max);
|
packet_put_int(c->local_window_max);
|
||||||
packet_put_int(c->local_maxpacket);
|
packet_put_int(c->local_maxpacket);
|
||||||
if (direct) {
|
if (strcmp(rtype, "direct-tcpip") == 0) {
|
||||||
/* target host, port */
|
/* target host, port */
|
||||||
packet_put_cstring(c->path);
|
packet_put_cstring(c->path);
|
||||||
packet_put_int(c->host_port);
|
packet_put_int(c->host_port);
|
||||||
|
} else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) {
|
||||||
|
/* target path */
|
||||||
|
packet_put_cstring(c->path);
|
||||||
|
} else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
|
||||||
|
/* listen path */
|
||||||
|
packet_put_cstring(c->path);
|
||||||
} else {
|
} else {
|
||||||
/* listen address, port */
|
/* listen address, port */
|
||||||
packet_put_cstring(c->path);
|
packet_put_cstring(c->path);
|
||||||
packet_put_int(local_port);
|
packet_put_int(local_port);
|
||||||
}
|
}
|
||||||
/* originator host and port */
|
if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
|
||||||
packet_put_cstring(remote_ipaddr);
|
/* reserved for future owner/mode info */
|
||||||
packet_put_int((u_int)remote_port);
|
packet_put_cstring("");
|
||||||
|
} else {
|
||||||
|
/* originator host and port */
|
||||||
|
packet_put_cstring(remote_ipaddr);
|
||||||
|
packet_put_int((u_int)remote_port);
|
||||||
|
}
|
||||||
packet_send();
|
packet_send();
|
||||||
} else {
|
} else {
|
||||||
packet_start(SSH_MSG_PORT_OPEN);
|
packet_start(SSH_MSG_PORT_OPEN);
|
||||||
|
@ -1479,14 +1500,18 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
||||||
if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
|
if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
|
||||||
nextstate = SSH_CHANNEL_OPENING;
|
nextstate = SSH_CHANNEL_OPENING;
|
||||||
rtype = "forwarded-tcpip";
|
rtype = "forwarded-tcpip";
|
||||||
|
} else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) {
|
||||||
|
nextstate = SSH_CHANNEL_OPENING;
|
||||||
|
rtype = "forwarded-streamlocal@openssh.com";
|
||||||
|
} else if (c->host_port == PORT_STREAMLOCAL) {
|
||||||
|
nextstate = SSH_CHANNEL_OPENING;
|
||||||
|
rtype = "direct-streamlocal@openssh.com";
|
||||||
|
} else if (c->host_port == 0) {
|
||||||
|
nextstate = SSH_CHANNEL_DYNAMIC;
|
||||||
|
rtype = "dynamic-tcpip";
|
||||||
} else {
|
} else {
|
||||||
if (c->host_port == 0) {
|
nextstate = SSH_CHANNEL_OPENING;
|
||||||
nextstate = SSH_CHANNEL_DYNAMIC;
|
rtype = "direct-tcpip";
|
||||||
rtype = "dynamic-tcpip";
|
|
||||||
} else {
|
|
||||||
nextstate = SSH_CHANNEL_OPENING;
|
|
||||||
rtype = "direct-tcpip";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addrlen = sizeof(addr);
|
addrlen = sizeof(addr);
|
||||||
|
@ -1499,7 +1524,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
|
||||||
c->notbefore = monotime() + 1;
|
c->notbefore = monotime() + 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
set_nodelay(newsock);
|
if (c->host_port != PORT_STREAMLOCAL)
|
||||||
|
set_nodelay(newsock);
|
||||||
nc = channel_new(rtype, nextstate, newsock, newsock, -1,
|
nc = channel_new(rtype, nextstate, newsock, newsock, -1,
|
||||||
c->local_window_max, c->local_maxpacket, 0, rtype, 1);
|
c->local_window_max, c->local_maxpacket, 0, rtype, 1);
|
||||||
nc->listening_port = c->listening_port;
|
nc->listening_port = c->listening_port;
|
||||||
|
@ -1988,6 +2014,8 @@ channel_handler_init_20(void)
|
||||||
channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
|
channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
|
||||||
channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
|
channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
|
||||||
channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener;
|
channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener;
|
||||||
|
channel_pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener;
|
||||||
|
channel_pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener;
|
||||||
channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
|
channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
|
||||||
channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
|
channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
|
||||||
channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
|
channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
|
||||||
|
@ -1998,6 +2026,8 @@ channel_handler_init_20(void)
|
||||||
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
|
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
|
||||||
channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
|
channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
|
||||||
channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener;
|
channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener;
|
||||||
|
channel_post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener;
|
||||||
|
channel_post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener;
|
||||||
channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
|
channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
|
||||||
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
|
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
|
||||||
channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
|
channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
|
||||||
|
@ -2638,7 +2668,7 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt)
|
||||||
originator_string = xstrdup("unknown (remote did not supply name)");
|
originator_string = xstrdup("unknown (remote did not supply name)");
|
||||||
}
|
}
|
||||||
packet_check_eom();
|
packet_check_eom();
|
||||||
c = channel_connect_to(host, host_port,
|
c = channel_connect_to_port(host, host_port,
|
||||||
"connected socket", originator_string);
|
"connected socket", originator_string);
|
||||||
free(originator_string);
|
free(originator_string);
|
||||||
free(host);
|
free(host);
|
||||||
|
@ -2705,20 +2735,20 @@ channel_set_af(int af)
|
||||||
*/
|
*/
|
||||||
static const char *
|
static const char *
|
||||||
channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
|
channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
|
||||||
int is_client, int gateway_ports)
|
int is_client, struct ForwardOptions *fwd_opts)
|
||||||
{
|
{
|
||||||
const char *addr = NULL;
|
const char *addr = NULL;
|
||||||
int wildcard = 0;
|
int wildcard = 0;
|
||||||
|
|
||||||
if (listen_addr == NULL) {
|
if (listen_addr == NULL) {
|
||||||
/* No address specified: default to gateway_ports setting */
|
/* No address specified: default to gateway_ports setting */
|
||||||
if (gateway_ports)
|
if (fwd_opts->gateway_ports)
|
||||||
wildcard = 1;
|
wildcard = 1;
|
||||||
} else if (gateway_ports || is_client) {
|
} else if (fwd_opts->gateway_ports || is_client) {
|
||||||
if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
|
if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
|
||||||
strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
|
strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
|
||||||
*listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
|
*listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
|
||||||
(!is_client && gateway_ports == 1)) {
|
(!is_client && fwd_opts->gateway_ports == 1)) {
|
||||||
wildcard = 1;
|
wildcard = 1;
|
||||||
/*
|
/*
|
||||||
* Notify client if they requested a specific listen
|
* Notify client if they requested a specific listen
|
||||||
|
@ -2752,9 +2782,8 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
channel_setup_fwd_listener(int type, const char *listen_addr,
|
channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
|
||||||
u_short listen_port, int *allocated_listen_port,
|
int *allocated_listen_port, struct ForwardOptions *fwd_opts)
|
||||||
const char *host_to_connect, u_short port_to_connect, int gateway_ports)
|
|
||||||
{
|
{
|
||||||
Channel *c;
|
Channel *c;
|
||||||
int sock, r, success = 0, wildcard = 0, is_client;
|
int sock, r, success = 0, wildcard = 0, is_client;
|
||||||
|
@ -2764,7 +2793,7 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
|
||||||
in_port_t *lport_p;
|
in_port_t *lport_p;
|
||||||
|
|
||||||
host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
|
host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
|
||||||
listen_addr : host_to_connect;
|
fwd->listen_host : fwd->connect_host;
|
||||||
is_client = (type == SSH_CHANNEL_PORT_LISTENER);
|
is_client = (type == SSH_CHANNEL_PORT_LISTENER);
|
||||||
|
|
||||||
if (host == NULL) {
|
if (host == NULL) {
|
||||||
|
@ -2777,9 +2806,9 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine the bind address, cf. channel_fwd_bind_addr() comment */
|
/* Determine the bind address, cf. channel_fwd_bind_addr() comment */
|
||||||
addr = channel_fwd_bind_addr(listen_addr, &wildcard,
|
addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard,
|
||||||
is_client, gateway_ports);
|
is_client, fwd_opts);
|
||||||
debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s",
|
debug3("%s: type %d wildcard %d addr %s", __func__,
|
||||||
type, wildcard, (addr == NULL) ? "NULL" : addr);
|
type, wildcard, (addr == NULL) ? "NULL" : addr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2790,15 +2819,14 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
|
||||||
hints.ai_family = IPv4or6;
|
hints.ai_family = IPv4or6;
|
||||||
hints.ai_flags = wildcard ? AI_PASSIVE : 0;
|
hints.ai_flags = wildcard ? AI_PASSIVE : 0;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
snprintf(strport, sizeof strport, "%d", listen_port);
|
snprintf(strport, sizeof strport, "%d", fwd->listen_port);
|
||||||
if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
|
if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
|
||||||
if (addr == NULL) {
|
if (addr == NULL) {
|
||||||
/* This really shouldn't happen */
|
/* This really shouldn't happen */
|
||||||
packet_disconnect("getaddrinfo: fatal error: %s",
|
packet_disconnect("getaddrinfo: fatal error: %s",
|
||||||
ssh_gai_strerror(r));
|
ssh_gai_strerror(r));
|
||||||
} else {
|
} else {
|
||||||
error("channel_setup_fwd_listener: "
|
error("%s: getaddrinfo(%.64s): %s", __func__, addr,
|
||||||
"getaddrinfo(%.64s): %s", addr,
|
|
||||||
ssh_gai_strerror(r));
|
ssh_gai_strerror(r));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2822,13 +2850,13 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
|
||||||
* If allocating a port for -R forwards, then use the
|
* If allocating a port for -R forwards, then use the
|
||||||
* same port for all address families.
|
* same port for all address families.
|
||||||
*/
|
*/
|
||||||
if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&
|
if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
|
||||||
allocated_listen_port != NULL && *allocated_listen_port > 0)
|
allocated_listen_port != NULL && *allocated_listen_port > 0)
|
||||||
*lport_p = htons(*allocated_listen_port);
|
*lport_p = htons(*allocated_listen_port);
|
||||||
|
|
||||||
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
|
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
|
||||||
strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
||||||
error("channel_setup_fwd_listener: getnameinfo failed");
|
error("%s: getnameinfo failed", __func__);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Create a port to listen for the host. */
|
/* Create a port to listen for the host. */
|
||||||
|
@ -2865,10 +2893,10 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* listen_port == 0 requests a dynamically allocated port -
|
* fwd->listen_port == 0 requests a dynamically allocated port -
|
||||||
* record what we got.
|
* record what we got.
|
||||||
*/
|
*/
|
||||||
if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&
|
if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
|
||||||
allocated_listen_port != NULL &&
|
allocated_listen_port != NULL &&
|
||||||
*allocated_listen_port == 0) {
|
*allocated_listen_port == 0) {
|
||||||
*allocated_listen_port = get_sock_port(sock, 1);
|
*allocated_listen_port = get_sock_port(sock, 1);
|
||||||
|
@ -2881,24 +2909,98 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
|
||||||
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
|
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
|
||||||
0, "port listener", 1);
|
0, "port listener", 1);
|
||||||
c->path = xstrdup(host);
|
c->path = xstrdup(host);
|
||||||
c->host_port = port_to_connect;
|
c->host_port = fwd->connect_port;
|
||||||
c->listening_addr = addr == NULL ? NULL : xstrdup(addr);
|
c->listening_addr = addr == NULL ? NULL : xstrdup(addr);
|
||||||
if (listen_port == 0 && allocated_listen_port != NULL &&
|
if (fwd->listen_port == 0 && allocated_listen_port != NULL &&
|
||||||
!(datafellows & SSH_BUG_DYNAMIC_RPORT))
|
!(datafellows & SSH_BUG_DYNAMIC_RPORT))
|
||||||
c->listening_port = *allocated_listen_port;
|
c->listening_port = *allocated_listen_port;
|
||||||
else
|
else
|
||||||
c->listening_port = listen_port;
|
c->listening_port = fwd->listen_port;
|
||||||
success = 1;
|
success = 1;
|
||||||
}
|
}
|
||||||
if (success == 0)
|
if (success == 0)
|
||||||
error("channel_setup_fwd_listener: cannot listen to port: %d",
|
error("%s: cannot listen to port: %d", __func__,
|
||||||
listen_port);
|
fwd->listen_port);
|
||||||
freeaddrinfo(aitop);
|
freeaddrinfo(aitop);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
channel_cancel_rport_listener(const char *host, u_short port)
|
channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd,
|
||||||
|
struct ForwardOptions *fwd_opts)
|
||||||
|
{
|
||||||
|
struct sockaddr_un sunaddr;
|
||||||
|
const char *path;
|
||||||
|
Channel *c;
|
||||||
|
int port, sock;
|
||||||
|
mode_t omask;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case SSH_CHANNEL_UNIX_LISTENER:
|
||||||
|
if (fwd->connect_path != NULL) {
|
||||||
|
if (strlen(fwd->connect_path) > sizeof(sunaddr.sun_path)) {
|
||||||
|
error("Local connecting path too long: %s",
|
||||||
|
fwd->connect_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
path = fwd->connect_path;
|
||||||
|
port = PORT_STREAMLOCAL;
|
||||||
|
} else {
|
||||||
|
if (fwd->connect_host == NULL) {
|
||||||
|
error("No forward host name.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (strlen(fwd->connect_host) >= NI_MAXHOST) {
|
||||||
|
error("Forward host name too long.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
path = fwd->connect_host;
|
||||||
|
port = fwd->connect_port;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SSH_CHANNEL_RUNIX_LISTENER:
|
||||||
|
path = fwd->listen_path;
|
||||||
|
port = PORT_STREAMLOCAL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("%s: unexpected channel type %d", __func__, type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fwd->listen_path == NULL) {
|
||||||
|
error("No forward path name.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (strlen(fwd->listen_path) > sizeof(sunaddr.sun_path)) {
|
||||||
|
error("Local listening path too long: %s", fwd->listen_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug3("%s: type %d path %s", __func__, type, fwd->listen_path);
|
||||||
|
|
||||||
|
/* Start a Unix domain listener. */
|
||||||
|
omask = umask(fwd_opts->streamlocal_bind_mask);
|
||||||
|
sock = unix_listener(fwd->listen_path, SSH_LISTEN_BACKLOG,
|
||||||
|
fwd_opts->streamlocal_bind_unlink);
|
||||||
|
umask(omask);
|
||||||
|
if (sock < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
debug("Local forwarding listening on path %s.", fwd->listen_path);
|
||||||
|
|
||||||
|
/* Allocate a channel number for the socket. */
|
||||||
|
c = channel_new("unix listener", type, sock, sock, -1,
|
||||||
|
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
|
||||||
|
0, "unix listener", 1);
|
||||||
|
c->path = xstrdup(path);
|
||||||
|
c->host_port = port;
|
||||||
|
c->listening_port = PORT_STREAMLOCAL;
|
||||||
|
c->listening_addr = xstrdup(fwd->listen_path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
channel_cancel_rport_listener_tcpip(const char *host, u_short port)
|
||||||
{
|
{
|
||||||
u_int i;
|
u_int i;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
@ -2917,13 +3019,44 @@ channel_cancel_rport_listener(const char *host, u_short port)
|
||||||
return (found);
|
return (found);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
channel_cancel_lport_listener(const char *lhost, u_short lport,
|
channel_cancel_rport_listener_streamlocal(const char *path)
|
||||||
int cport, int gateway_ports)
|
|
||||||
{
|
{
|
||||||
u_int i;
|
u_int i;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, gateway_ports);
|
|
||||||
|
for (i = 0; i < channels_alloc; i++) {
|
||||||
|
Channel *c = channels[i];
|
||||||
|
if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER)
|
||||||
|
continue;
|
||||||
|
if (c->path == NULL)
|
||||||
|
continue;
|
||||||
|
if (strcmp(c->path, path) == 0) {
|
||||||
|
debug2("%s: close channel %d", __func__, i);
|
||||||
|
channel_free(c);
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (found);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
channel_cancel_rport_listener(struct Forward *fwd)
|
||||||
|
{
|
||||||
|
if (fwd->listen_path != NULL)
|
||||||
|
return channel_cancel_rport_listener_streamlocal(fwd->listen_path);
|
||||||
|
else
|
||||||
|
return channel_cancel_rport_listener_tcpip(fwd->listen_host, fwd->listen_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport,
|
||||||
|
int cport, struct ForwardOptions *fwd_opts)
|
||||||
|
{
|
||||||
|
u_int i;
|
||||||
|
int found = 0;
|
||||||
|
const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts);
|
||||||
|
|
||||||
for (i = 0; i < channels_alloc; i++) {
|
for (i = 0; i < channels_alloc; i++) {
|
||||||
Channel *c = channels[i];
|
Channel *c = channels[i];
|
||||||
|
@ -2952,24 +3085,68 @@ channel_cancel_lport_listener(const char *lhost, u_short lport,
|
||||||
return (found);
|
return (found);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
channel_cancel_lport_listener_streamlocal(const char *path)
|
||||||
|
{
|
||||||
|
u_int i;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
if (path == NULL) {
|
||||||
|
error("%s: no path specified.", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < channels_alloc; i++) {
|
||||||
|
Channel *c = channels[i];
|
||||||
|
if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER)
|
||||||
|
continue;
|
||||||
|
if (c->listening_addr == NULL)
|
||||||
|
continue;
|
||||||
|
if (strcmp(c->listening_addr, path) == 0) {
|
||||||
|
debug2("%s: close channel %d", __func__, i);
|
||||||
|
channel_free(c);
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (found);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
channel_cancel_lport_listener(struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts)
|
||||||
|
{
|
||||||
|
if (fwd->listen_path != NULL)
|
||||||
|
return channel_cancel_lport_listener_streamlocal(fwd->listen_path);
|
||||||
|
else
|
||||||
|
return channel_cancel_lport_listener_tcpip(fwd->listen_host, fwd->listen_port, cport, fwd_opts);
|
||||||
|
}
|
||||||
|
|
||||||
/* protocol local port fwd, used by ssh (and sshd in v1) */
|
/* protocol local port fwd, used by ssh (and sshd in v1) */
|
||||||
int
|
int
|
||||||
channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,
|
channel_setup_local_fwd_listener(struct Forward *fwd, struct ForwardOptions *fwd_opts)
|
||||||
const char *host_to_connect, u_short port_to_connect, int gateway_ports)
|
|
||||||
{
|
{
|
||||||
return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
|
if (fwd->listen_path != NULL) {
|
||||||
listen_host, listen_port, NULL, host_to_connect, port_to_connect,
|
return channel_setup_fwd_listener_streamlocal(
|
||||||
gateway_ports);
|
SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts);
|
||||||
|
} else {
|
||||||
|
return channel_setup_fwd_listener_tcpip(SSH_CHANNEL_PORT_LISTENER,
|
||||||
|
fwd, NULL, fwd_opts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* protocol v2 remote port fwd, used by sshd */
|
/* protocol v2 remote port fwd, used by sshd */
|
||||||
int
|
int
|
||||||
channel_setup_remote_fwd_listener(const char *listen_address,
|
channel_setup_remote_fwd_listener(struct Forward *fwd,
|
||||||
u_short listen_port, int *allocated_listen_port, int gateway_ports)
|
int *allocated_listen_port, struct ForwardOptions *fwd_opts)
|
||||||
{
|
{
|
||||||
return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER,
|
if (fwd->listen_path != NULL) {
|
||||||
listen_address, listen_port, allocated_listen_port,
|
return channel_setup_fwd_listener_streamlocal(
|
||||||
NULL, 0, gateway_ports);
|
SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts);
|
||||||
|
} else {
|
||||||
|
return channel_setup_fwd_listener_tcpip(
|
||||||
|
SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port,
|
||||||
|
fwd_opts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3000,27 +3177,32 @@ channel_rfwd_bind_host(const char *listen_host)
|
||||||
* channel_update_permitted_opens().
|
* channel_update_permitted_opens().
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
|
channel_request_remote_forwarding(struct Forward *fwd)
|
||||||
const char *host_to_connect, u_short port_to_connect)
|
|
||||||
{
|
{
|
||||||
int type, success = 0, idx = -1;
|
int type, success = 0, idx = -1;
|
||||||
|
|
||||||
/* Send the forward request to the remote side. */
|
/* Send the forward request to the remote side. */
|
||||||
if (compat20) {
|
if (compat20) {
|
||||||
packet_start(SSH2_MSG_GLOBAL_REQUEST);
|
packet_start(SSH2_MSG_GLOBAL_REQUEST);
|
||||||
packet_put_cstring("tcpip-forward");
|
if (fwd->listen_path != NULL) {
|
||||||
packet_put_char(1); /* boolean: want reply */
|
packet_put_cstring("streamlocal-forward@openssh.com");
|
||||||
packet_put_cstring(channel_rfwd_bind_host(listen_host));
|
packet_put_char(1); /* boolean: want reply */
|
||||||
packet_put_int(listen_port);
|
packet_put_cstring(fwd->listen_path);
|
||||||
|
} else {
|
||||||
|
packet_put_cstring("tcpip-forward");
|
||||||
|
packet_put_char(1); /* boolean: want reply */
|
||||||
|
packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host));
|
||||||
|
packet_put_int(fwd->listen_port);
|
||||||
|
}
|
||||||
packet_send();
|
packet_send();
|
||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
/* Assume that server accepts the request */
|
/* Assume that server accepts the request */
|
||||||
success = 1;
|
success = 1;
|
||||||
} else {
|
} else if (fwd->listen_path == NULL) {
|
||||||
packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
|
packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
|
||||||
packet_put_int(listen_port);
|
packet_put_int(fwd->listen_port);
|
||||||
packet_put_cstring(host_to_connect);
|
packet_put_cstring(fwd->connect_host);
|
||||||
packet_put_int(port_to_connect);
|
packet_put_int(fwd->connect_port);
|
||||||
packet_send();
|
packet_send();
|
||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
|
|
||||||
|
@ -3037,24 +3219,43 @@ channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
|
||||||
packet_disconnect("Protocol error for port forward request:"
|
packet_disconnect("Protocol error for port forward request:"
|
||||||
"received packet type %d.", type);
|
"received packet type %d.", type);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
logit("Warning: Server does not support remote stream local forwarding.");
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
/* Record that connection to this host/port is permitted. */
|
/* Record that connection to this host/port is permitted. */
|
||||||
permitted_opens = xrealloc(permitted_opens,
|
permitted_opens = xrealloc(permitted_opens,
|
||||||
num_permitted_opens + 1, sizeof(*permitted_opens));
|
num_permitted_opens + 1, sizeof(*permitted_opens));
|
||||||
idx = num_permitted_opens++;
|
idx = num_permitted_opens++;
|
||||||
permitted_opens[idx].host_to_connect = xstrdup(host_to_connect);
|
if (fwd->connect_path != NULL) {
|
||||||
permitted_opens[idx].port_to_connect = port_to_connect;
|
permitted_opens[idx].host_to_connect =
|
||||||
permitted_opens[idx].listen_host = listen_host ?
|
xstrdup(fwd->connect_path);
|
||||||
xstrdup(listen_host) : NULL;
|
permitted_opens[idx].port_to_connect =
|
||||||
permitted_opens[idx].listen_port = listen_port;
|
PORT_STREAMLOCAL;
|
||||||
|
} else {
|
||||||
|
permitted_opens[idx].host_to_connect =
|
||||||
|
xstrdup(fwd->connect_host);
|
||||||
|
permitted_opens[idx].port_to_connect =
|
||||||
|
fwd->connect_port;
|
||||||
|
}
|
||||||
|
if (fwd->listen_path != NULL) {
|
||||||
|
permitted_opens[idx].listen_host = NULL;
|
||||||
|
permitted_opens[idx].listen_path =
|
||||||
|
xstrdup(fwd->listen_path);
|
||||||
|
permitted_opens[idx].listen_port = PORT_STREAMLOCAL;
|
||||||
|
} else {
|
||||||
|
permitted_opens[idx].listen_host =
|
||||||
|
fwd->listen_host ? xstrdup(fwd->listen_host) : NULL;
|
||||||
|
permitted_opens[idx].listen_path = NULL;
|
||||||
|
permitted_opens[idx].listen_port = fwd->listen_port;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (idx);
|
return (idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
open_match(ForwardPermission *allowed_open, const char *requestedhost,
|
open_match(ForwardPermission *allowed_open, const char *requestedhost,
|
||||||
u_short requestedport)
|
int requestedport)
|
||||||
{
|
{
|
||||||
if (allowed_open->host_to_connect == NULL)
|
if (allowed_open->host_to_connect == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3067,14 +3268,14 @@ open_match(ForwardPermission *allowed_open, const char *requestedhost,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that in he listen host/port case
|
* Note that in the listen host/port case
|
||||||
* we don't support FWD_PERMIT_ANY_PORT and
|
* we don't support FWD_PERMIT_ANY_PORT and
|
||||||
* need to translate between the configured-host (listen_host)
|
* need to translate between the configured-host (listen_host)
|
||||||
* and what we've sent to the remote server (channel_rfwd_bind_host)
|
* and what we've sent to the remote server (channel_rfwd_bind_host)
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
open_listen_match(ForwardPermission *allowed_open, const char *requestedhost,
|
open_listen_match_tcpip(ForwardPermission *allowed_open,
|
||||||
u_short requestedport, int translate)
|
const char *requestedhost, u_short requestedport, int translate)
|
||||||
{
|
{
|
||||||
const char *allowed_host;
|
const char *allowed_host;
|
||||||
|
|
||||||
|
@ -3094,12 +3295,26 @@ open_listen_match(ForwardPermission *allowed_open, const char *requestedhost,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
open_listen_match_streamlocal(ForwardPermission *allowed_open,
|
||||||
|
const char *requestedpath)
|
||||||
|
{
|
||||||
|
if (allowed_open->host_to_connect == NULL)
|
||||||
|
return 0;
|
||||||
|
if (allowed_open->listen_port != PORT_STREAMLOCAL)
|
||||||
|
return 0;
|
||||||
|
if (allowed_open->listen_path == NULL ||
|
||||||
|
strcmp(allowed_open->listen_path, requestedpath) != 0)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Request cancellation of remote forwarding of connection host:port from
|
* Request cancellation of remote forwarding of connection host:port from
|
||||||
* local side.
|
* local side.
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
channel_request_rforward_cancel(const char *host, u_short port)
|
channel_request_rforward_cancel_tcpip(const char *host, u_short port)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -3107,7 +3322,7 @@ channel_request_rforward_cancel(const char *host, u_short port)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (i = 0; i < num_permitted_opens; i++) {
|
for (i = 0; i < num_permitted_opens; i++) {
|
||||||
if (open_listen_match(&permitted_opens[i], host, port, 0))
|
if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i >= num_permitted_opens) {
|
if (i >= num_permitted_opens) {
|
||||||
|
@ -3121,52 +3336,104 @@ channel_request_rforward_cancel(const char *host, u_short port)
|
||||||
packet_put_int(port);
|
packet_put_int(port);
|
||||||
packet_send();
|
packet_send();
|
||||||
|
|
||||||
permitted_opens[i].port_to_connect = 0;
|
|
||||||
permitted_opens[i].listen_port = 0;
|
permitted_opens[i].listen_port = 0;
|
||||||
|
permitted_opens[i].port_to_connect = 0;
|
||||||
free(permitted_opens[i].host_to_connect);
|
free(permitted_opens[i].host_to_connect);
|
||||||
permitted_opens[i].host_to_connect = NULL;
|
permitted_opens[i].host_to_connect = NULL;
|
||||||
free(permitted_opens[i].listen_host);
|
free(permitted_opens[i].listen_host);
|
||||||
permitted_opens[i].listen_host = NULL;
|
permitted_opens[i].listen_host = NULL;
|
||||||
|
permitted_opens[i].listen_path = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request cancellation of remote forwarding of Unix domain socket
|
||||||
|
* path from local side.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
channel_request_rforward_cancel_streamlocal(const char *path)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!compat20)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (i = 0; i < num_permitted_opens; i++) {
|
||||||
|
if (open_listen_match_streamlocal(&permitted_opens[i], path))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i >= num_permitted_opens) {
|
||||||
|
debug("%s: requested forward not found", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
packet_start(SSH2_MSG_GLOBAL_REQUEST);
|
||||||
|
packet_put_cstring("cancel-streamlocal-forward@openssh.com");
|
||||||
|
packet_put_char(0);
|
||||||
|
packet_put_cstring(path);
|
||||||
|
packet_send();
|
||||||
|
|
||||||
|
permitted_opens[i].listen_port = 0;
|
||||||
|
permitted_opens[i].port_to_connect = 0;
|
||||||
|
free(permitted_opens[i].host_to_connect);
|
||||||
|
permitted_opens[i].host_to_connect = NULL;
|
||||||
|
permitted_opens[i].listen_host = NULL;
|
||||||
|
free(permitted_opens[i].listen_path);
|
||||||
|
permitted_opens[i].listen_path = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request cancellation of remote forwarding of a connection from local side.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
channel_request_rforward_cancel(struct Forward *fwd)
|
||||||
|
{
|
||||||
|
if (fwd->listen_path != NULL) {
|
||||||
|
return (channel_request_rforward_cancel_streamlocal(
|
||||||
|
fwd->listen_path));
|
||||||
|
} else {
|
||||||
|
return (channel_request_rforward_cancel_tcpip(fwd->listen_host,
|
||||||
|
fwd->listen_port ? fwd->listen_port : fwd->allocated_port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
|
* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
|
||||||
* listening for the port, and sends back a success reply (or disconnect
|
* listening for the port, and sends back a success reply (or disconnect
|
||||||
* message if there was an error).
|
* message if there was an error).
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
channel_input_port_forward_request(int is_root, int gateway_ports)
|
channel_input_port_forward_request(int is_root, struct ForwardOptions *fwd_opts)
|
||||||
{
|
{
|
||||||
u_short port, host_port;
|
|
||||||
int success = 0;
|
int success = 0;
|
||||||
char *hostname;
|
struct Forward fwd;
|
||||||
|
|
||||||
/* Get arguments from the packet. */
|
/* Get arguments from the packet. */
|
||||||
port = packet_get_int();
|
memset(&fwd, 0, sizeof(fwd));
|
||||||
hostname = packet_get_string(NULL);
|
fwd.listen_port = packet_get_int();
|
||||||
host_port = packet_get_int();
|
fwd.connect_host = packet_get_string(NULL);
|
||||||
|
fwd.connect_port = packet_get_int();
|
||||||
|
|
||||||
#ifndef HAVE_CYGWIN
|
#ifndef HAVE_CYGWIN
|
||||||
/*
|
/*
|
||||||
* Check that an unprivileged user is not trying to forward a
|
* Check that an unprivileged user is not trying to forward a
|
||||||
* privileged port.
|
* privileged port.
|
||||||
*/
|
*/
|
||||||
if (port < IPPORT_RESERVED && !is_root)
|
if (fwd.listen_port < IPPORT_RESERVED && !is_root)
|
||||||
packet_disconnect(
|
packet_disconnect(
|
||||||
"Requested forwarding of port %d but user is not root.",
|
"Requested forwarding of port %d but user is not root.",
|
||||||
port);
|
fwd.listen_port);
|
||||||
if (host_port == 0)
|
if (fwd.connect_port == 0)
|
||||||
packet_disconnect("Dynamic forwarding denied.");
|
packet_disconnect("Dynamic forwarding denied.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Initiate forwarding */
|
/* Initiate forwarding */
|
||||||
success = channel_setup_local_fwd_listener(NULL, port, hostname,
|
success = channel_setup_local_fwd_listener(&fwd, fwd_opts);
|
||||||
host_port, gateway_ports);
|
|
||||||
|
|
||||||
/* Free the argument string. */
|
/* Free the argument string. */
|
||||||
free(hostname);
|
free(fwd.connect_host);
|
||||||
|
|
||||||
return (success ? 0 : -1);
|
return (success ? 0 : -1);
|
||||||
}
|
}
|
||||||
|
@ -3193,6 +3460,7 @@ channel_add_permitted_opens(char *host, int port)
|
||||||
permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);
|
permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);
|
||||||
permitted_opens[num_permitted_opens].port_to_connect = port;
|
permitted_opens[num_permitted_opens].port_to_connect = port;
|
||||||
permitted_opens[num_permitted_opens].listen_host = NULL;
|
permitted_opens[num_permitted_opens].listen_host = NULL;
|
||||||
|
permitted_opens[num_permitted_opens].listen_path = NULL;
|
||||||
permitted_opens[num_permitted_opens].listen_port = 0;
|
permitted_opens[num_permitted_opens].listen_port = 0;
|
||||||
num_permitted_opens++;
|
num_permitted_opens++;
|
||||||
|
|
||||||
|
@ -3227,6 +3495,8 @@ channel_update_permitted_opens(int idx, int newport)
|
||||||
permitted_opens[idx].host_to_connect = NULL;
|
permitted_opens[idx].host_to_connect = NULL;
|
||||||
free(permitted_opens[idx].listen_host);
|
free(permitted_opens[idx].listen_host);
|
||||||
permitted_opens[idx].listen_host = NULL;
|
permitted_opens[idx].listen_host = NULL;
|
||||||
|
free(permitted_opens[idx].listen_path);
|
||||||
|
permitted_opens[idx].listen_path = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3241,6 +3511,7 @@ channel_add_adm_permitted_opens(char *host, int port)
|
||||||
= xstrdup(host);
|
= xstrdup(host);
|
||||||
permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port;
|
permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port;
|
||||||
permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL;
|
permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL;
|
||||||
|
permitted_adm_opens[num_adm_permitted_opens].listen_path = NULL;
|
||||||
permitted_adm_opens[num_adm_permitted_opens].listen_port = 0;
|
permitted_adm_opens[num_adm_permitted_opens].listen_port = 0;
|
||||||
return ++num_adm_permitted_opens;
|
return ++num_adm_permitted_opens;
|
||||||
}
|
}
|
||||||
|
@ -3262,6 +3533,7 @@ channel_clear_permitted_opens(void)
|
||||||
for (i = 0; i < num_permitted_opens; i++) {
|
for (i = 0; i < num_permitted_opens; i++) {
|
||||||
free(permitted_opens[i].host_to_connect);
|
free(permitted_opens[i].host_to_connect);
|
||||||
free(permitted_opens[i].listen_host);
|
free(permitted_opens[i].listen_host);
|
||||||
|
free(permitted_opens[i].listen_path);
|
||||||
}
|
}
|
||||||
free(permitted_opens);
|
free(permitted_opens);
|
||||||
permitted_opens = NULL;
|
permitted_opens = NULL;
|
||||||
|
@ -3276,6 +3548,7 @@ channel_clear_adm_permitted_opens(void)
|
||||||
for (i = 0; i < num_adm_permitted_opens; i++) {
|
for (i = 0; i < num_adm_permitted_opens; i++) {
|
||||||
free(permitted_adm_opens[i].host_to_connect);
|
free(permitted_adm_opens[i].host_to_connect);
|
||||||
free(permitted_adm_opens[i].listen_host);
|
free(permitted_adm_opens[i].listen_host);
|
||||||
|
free(permitted_adm_opens[i].listen_path);
|
||||||
}
|
}
|
||||||
free(permitted_adm_opens);
|
free(permitted_adm_opens);
|
||||||
permitted_adm_opens = NULL;
|
permitted_adm_opens = NULL;
|
||||||
|
@ -3319,16 +3592,27 @@ static int
|
||||||
connect_next(struct channel_connect *cctx)
|
connect_next(struct channel_connect *cctx)
|
||||||
{
|
{
|
||||||
int sock, saved_errno;
|
int sock, saved_errno;
|
||||||
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
|
struct sockaddr_un *sunaddr;
|
||||||
|
char ntop[NI_MAXHOST], strport[MAX(NI_MAXSERV,sizeof(sunaddr->sun_path))];
|
||||||
|
|
||||||
for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
|
for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
|
||||||
if (cctx->ai->ai_family != AF_INET &&
|
switch (cctx->ai->ai_family) {
|
||||||
cctx->ai->ai_family != AF_INET6)
|
case AF_UNIX:
|
||||||
continue;
|
/* unix:pathname instead of host:port */
|
||||||
if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
|
sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr;
|
||||||
ntop, sizeof(ntop), strport, sizeof(strport),
|
strlcpy(ntop, "unix", sizeof(ntop));
|
||||||
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
strlcpy(strport, sunaddr->sun_path, sizeof(strport));
|
||||||
error("connect_next: getnameinfo failed");
|
break;
|
||||||
|
case AF_INET:
|
||||||
|
case AF_INET6:
|
||||||
|
if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
|
||||||
|
ntop, sizeof(ntop), strport, sizeof(strport),
|
||||||
|
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
||||||
|
error("connect_next: getnameinfo failed");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
|
if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
|
||||||
|
@ -3351,10 +3635,11 @@ connect_next(struct channel_connect *cctx)
|
||||||
errno = saved_errno;
|
errno = saved_errno;
|
||||||
continue; /* fail -- try next */
|
continue; /* fail -- try next */
|
||||||
}
|
}
|
||||||
|
if (cctx->ai->ai_family != AF_UNIX)
|
||||||
|
set_nodelay(sock);
|
||||||
debug("connect_next: host %.100s ([%.100s]:%s) "
|
debug("connect_next: host %.100s ([%.100s]:%s) "
|
||||||
"in progress, fd=%d", cctx->host, ntop, strport, sock);
|
"in progress, fd=%d", cctx->host, ntop, strport, sock);
|
||||||
cctx->ai = cctx->ai->ai_next;
|
cctx->ai = cctx->ai->ai_next;
|
||||||
set_nodelay(sock);
|
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -3364,14 +3649,18 @@ static void
|
||||||
channel_connect_ctx_free(struct channel_connect *cctx)
|
channel_connect_ctx_free(struct channel_connect *cctx)
|
||||||
{
|
{
|
||||||
free(cctx->host);
|
free(cctx->host);
|
||||||
if (cctx->aitop)
|
if (cctx->aitop) {
|
||||||
freeaddrinfo(cctx->aitop);
|
if (cctx->aitop->ai_family == AF_UNIX)
|
||||||
|
free(cctx->aitop);
|
||||||
|
else
|
||||||
|
freeaddrinfo(cctx->aitop);
|
||||||
|
}
|
||||||
memset(cctx, 0, sizeof(*cctx));
|
memset(cctx, 0, sizeof(*cctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return CONNECTING channel to remote host, port */
|
/* Return CONNECTING channel to remote host:port or local socket path */
|
||||||
static Channel *
|
static Channel *
|
||||||
connect_to(const char *host, u_short port, char *ctype, char *rname)
|
connect_to(const char *name, int port, char *ctype, char *rname)
|
||||||
{
|
{
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
int gaierr;
|
int gaierr;
|
||||||
|
@ -3381,23 +3670,51 @@ connect_to(const char *host, u_short port, char *ctype, char *rname)
|
||||||
Channel *c;
|
Channel *c;
|
||||||
|
|
||||||
memset(&cctx, 0, sizeof(cctx));
|
memset(&cctx, 0, sizeof(cctx));
|
||||||
memset(&hints, 0, sizeof(hints));
|
|
||||||
hints.ai_family = IPv4or6;
|
if (port == PORT_STREAMLOCAL) {
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
struct sockaddr_un *sunaddr;
|
||||||
snprintf(strport, sizeof strport, "%d", port);
|
struct addrinfo *ai;
|
||||||
if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) {
|
|
||||||
error("connect_to %.100s: unknown host (%s)", host,
|
if (strlen(name) > sizeof(sunaddr->sun_path)) {
|
||||||
ssh_gai_strerror(gaierr));
|
error("%.100s: %.100s", name, strerror(ENAMETOOLONG));
|
||||||
return NULL;
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fake up a struct addrinfo for AF_UNIX connections.
|
||||||
|
* channel_connect_ctx_free() must check ai_family
|
||||||
|
* and use free() not freeaddirinfo() for AF_UNIX.
|
||||||
|
*/
|
||||||
|
ai = xmalloc(sizeof(*ai) + sizeof(*sunaddr));
|
||||||
|
memset(ai, 0, sizeof(*ai) + sizeof(*sunaddr));
|
||||||
|
ai->ai_addr = (struct sockaddr *)(ai + 1);
|
||||||
|
ai->ai_addrlen = sizeof(*sunaddr);
|
||||||
|
ai->ai_family = AF_UNIX;
|
||||||
|
ai->ai_socktype = SOCK_STREAM;
|
||||||
|
ai->ai_protocol = PF_UNSPEC;
|
||||||
|
sunaddr = (struct sockaddr_un *)ai->ai_addr;
|
||||||
|
sunaddr->sun_family = AF_UNIX;
|
||||||
|
strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path));
|
||||||
|
cctx.aitop = ai;
|
||||||
|
} else {
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = IPv4or6;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
snprintf(strport, sizeof strport, "%d", port);
|
||||||
|
if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) != 0) {
|
||||||
|
error("connect_to %.100s: unknown host (%s)", name,
|
||||||
|
ssh_gai_strerror(gaierr));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cctx.host = xstrdup(host);
|
cctx.host = xstrdup(name);
|
||||||
cctx.port = port;
|
cctx.port = port;
|
||||||
cctx.ai = cctx.aitop;
|
cctx.ai = cctx.aitop;
|
||||||
|
|
||||||
if ((sock = connect_next(&cctx)) == -1) {
|
if ((sock = connect_next(&cctx)) == -1) {
|
||||||
error("connect to %.100s port %d failed: %s",
|
error("connect to %.100s port %d failed: %s",
|
||||||
host, port, strerror(errno));
|
name, port, strerror(errno));
|
||||||
channel_connect_ctx_free(&cctx);
|
channel_connect_ctx_free(&cctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -3414,7 +3731,7 @@ channel_connect_by_listen_address(const char *listen_host,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < num_permitted_opens; i++) {
|
for (i = 0; i < num_permitted_opens; i++) {
|
||||||
if (open_listen_match(&permitted_opens[i], listen_host,
|
if (open_listen_match_tcpip(&permitted_opens[i], listen_host,
|
||||||
listen_port, 1)) {
|
listen_port, 1)) {
|
||||||
return connect_to(
|
return connect_to(
|
||||||
permitted_opens[i].host_to_connect,
|
permitted_opens[i].host_to_connect,
|
||||||
|
@ -3426,9 +3743,26 @@ channel_connect_by_listen_address(const char *listen_host,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Channel *
|
||||||
|
channel_connect_by_listen_path(const char *path, char *ctype, char *rname)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_permitted_opens; i++) {
|
||||||
|
if (open_listen_match_streamlocal(&permitted_opens[i], path)) {
|
||||||
|
return connect_to(
|
||||||
|
permitted_opens[i].host_to_connect,
|
||||||
|
permitted_opens[i].port_to_connect, ctype, rname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("WARNING: Server requests forwarding for unknown path %.100s",
|
||||||
|
path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if connecting to that port is permitted and connect. */
|
/* Check if connecting to that port is permitted and connect. */
|
||||||
Channel *
|
Channel *
|
||||||
channel_connect_to(const char *host, u_short port, char *ctype, char *rname)
|
channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname)
|
||||||
{
|
{
|
||||||
int i, permit, permit_adm = 1;
|
int i, permit, permit_adm = 1;
|
||||||
|
|
||||||
|
@ -3458,6 +3792,38 @@ channel_connect_to(const char *host, u_short port, char *ctype, char *rname)
|
||||||
return connect_to(host, port, ctype, rname);
|
return connect_to(host, port, ctype, rname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if connecting to that path is permitted and connect. */
|
||||||
|
Channel *
|
||||||
|
channel_connect_to_path(const char *path, char *ctype, char *rname)
|
||||||
|
{
|
||||||
|
int i, permit, permit_adm = 1;
|
||||||
|
|
||||||
|
permit = all_opens_permitted;
|
||||||
|
if (!permit) {
|
||||||
|
for (i = 0; i < num_permitted_opens; i++)
|
||||||
|
if (open_match(&permitted_opens[i], path, PORT_STREAMLOCAL)) {
|
||||||
|
permit = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_adm_permitted_opens > 0) {
|
||||||
|
permit_adm = 0;
|
||||||
|
for (i = 0; i < num_adm_permitted_opens; i++)
|
||||||
|
if (open_match(&permitted_adm_opens[i], path, PORT_STREAMLOCAL)) {
|
||||||
|
permit_adm = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!permit || !permit_adm) {
|
||||||
|
logit("Received request to connect to path %.100s, "
|
||||||
|
"but the request was denied.", path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return connect_to(path, PORT_STREAMLOCAL, ctype, rname);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
channel_send_window_changes(void)
|
channel_send_window_changes(void)
|
||||||
{
|
{
|
||||||
|
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -56,7 +56,9 @@
|
||||||
#define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */
|
#define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */
|
||||||
#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */
|
#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */
|
||||||
#define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */
|
#define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */
|
||||||
#define SSH_CHANNEL_MAX_TYPE 18
|
#define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */
|
||||||
|
#define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */
|
||||||
|
#define SSH_CHANNEL_MAX_TYPE 20
|
||||||
|
|
||||||
#define CHANNEL_CANCEL_PORT_STATIC -1
|
#define CHANNEL_CANCEL_PORT_STATIC -1
|
||||||
|
|
||||||
|
@ -254,6 +256,8 @@ char *channel_open_message(void);
|
||||||
int channel_find_open(void);
|
int channel_find_open(void);
|
||||||
|
|
||||||
/* tcp forwarding */
|
/* tcp forwarding */
|
||||||
|
struct Forward;
|
||||||
|
struct ForwardOptions;
|
||||||
void channel_set_af(int af);
|
void channel_set_af(int af);
|
||||||
void channel_permit_all_opens(void);
|
void channel_permit_all_opens(void);
|
||||||
void channel_add_permitted_opens(char *, int);
|
void channel_add_permitted_opens(char *, int);
|
||||||
|
@ -263,19 +267,19 @@ void channel_update_permitted_opens(int, int);
|
||||||
void channel_clear_permitted_opens(void);
|
void channel_clear_permitted_opens(void);
|
||||||
void channel_clear_adm_permitted_opens(void);
|
void channel_clear_adm_permitted_opens(void);
|
||||||
void channel_print_adm_permitted_opens(void);
|
void channel_print_adm_permitted_opens(void);
|
||||||
int channel_input_port_forward_request(int, int);
|
int channel_input_port_forward_request(int, struct ForwardOptions *);
|
||||||
Channel *channel_connect_to(const char *, u_short, char *, char *);
|
Channel *channel_connect_to_port(const char *, u_short, char *, char *);
|
||||||
|
Channel *channel_connect_to_path(const char *, char *, char *);
|
||||||
Channel *channel_connect_stdio_fwd(const char*, u_short, int, int);
|
Channel *channel_connect_stdio_fwd(const char*, u_short, int, int);
|
||||||
Channel *channel_connect_by_listen_address(const char *, u_short,
|
Channel *channel_connect_by_listen_address(const char *, u_short,
|
||||||
char *, char *);
|
char *, char *);
|
||||||
int channel_request_remote_forwarding(const char *, u_short,
|
Channel *channel_connect_by_listen_path(const char *, char *, char *);
|
||||||
const char *, u_short);
|
int channel_request_remote_forwarding(struct Forward *);
|
||||||
int channel_setup_local_fwd_listener(const char *, u_short,
|
int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *);
|
||||||
const char *, u_short, int);
|
int channel_request_rforward_cancel(struct Forward *);
|
||||||
int channel_request_rforward_cancel(const char *host, u_short port);
|
int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *);
|
||||||
int channel_setup_remote_fwd_listener(const char *, u_short, int *, int);
|
int channel_cancel_rport_listener(struct Forward *);
|
||||||
int channel_cancel_rport_listener(const char *, u_short);
|
int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *);
|
||||||
int channel_cancel_lport_listener(const char *, u_short, int, int);
|
|
||||||
int permitopen_port(const char *);
|
int permitopen_port(const char *);
|
||||||
|
|
||||||
/* x11 forwarding */
|
/* x11 forwarding */
|
||||||
|
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -100,13 +100,13 @@
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
#include "kex.h"
|
#include "kex.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "readconf.h"
|
#include "readconf.h"
|
||||||
#include "clientloop.h"
|
#include "clientloop.h"
|
||||||
#include "sshconnect.h"
|
#include "sshconnect.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "atomicio.h"
|
#include "atomicio.h"
|
||||||
#include "sshpty.h"
|
#include "sshpty.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
#include "msg.h"
|
#include "msg.h"
|
||||||
#include "roaming.h"
|
#include "roaming.h"
|
||||||
|
@ -871,13 +871,11 @@ static void
|
||||||
process_cmdline(void)
|
process_cmdline(void)
|
||||||
{
|
{
|
||||||
void (*handler)(int);
|
void (*handler)(int);
|
||||||
char *s, *cmd, *cancel_host;
|
char *s, *cmd;
|
||||||
int delete = 0, local = 0, remote = 0, dynamic = 0;
|
int ok, delete = 0, local = 0, remote = 0, dynamic = 0;
|
||||||
int cancel_port, ok;
|
struct Forward fwd;
|
||||||
Forward fwd;
|
|
||||||
|
|
||||||
memset(&fwd, 0, sizeof(fwd));
|
memset(&fwd, 0, sizeof(fwd));
|
||||||
fwd.listen_host = fwd.connect_host = NULL;
|
|
||||||
|
|
||||||
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
|
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
|
||||||
handler = signal(SIGINT, SIG_IGN);
|
handler = signal(SIGINT, SIG_IGN);
|
||||||
|
@ -943,29 +941,20 @@ process_cmdline(void)
|
||||||
|
|
||||||
/* XXX update list of forwards in options */
|
/* XXX update list of forwards in options */
|
||||||
if (delete) {
|
if (delete) {
|
||||||
cancel_port = 0;
|
/* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */
|
||||||
cancel_host = hpdelim(&s); /* may be NULL */
|
if (!parse_forward(&fwd, s, 1, 0)) {
|
||||||
if (s != NULL) {
|
logit("Bad forwarding close specification.");
|
||||||
cancel_port = a2port(s);
|
|
||||||
cancel_host = cleanhostname(cancel_host);
|
|
||||||
} else {
|
|
||||||
cancel_port = a2port(cancel_host);
|
|
||||||
cancel_host = NULL;
|
|
||||||
}
|
|
||||||
if (cancel_port <= 0) {
|
|
||||||
logit("Bad forwarding close port");
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (remote)
|
if (remote)
|
||||||
ok = channel_request_rforward_cancel(cancel_host,
|
ok = channel_request_rforward_cancel(&fwd) == 0;
|
||||||
cancel_port) == 0;
|
|
||||||
else if (dynamic)
|
else if (dynamic)
|
||||||
ok = channel_cancel_lport_listener(cancel_host,
|
ok = channel_cancel_lport_listener(&fwd,
|
||||||
cancel_port, 0, options.gateway_ports) > 0;
|
0, &options.fwd_opts) > 0;
|
||||||
else
|
else
|
||||||
ok = channel_cancel_lport_listener(cancel_host,
|
ok = channel_cancel_lport_listener(&fwd,
|
||||||
cancel_port, CHANNEL_CANCEL_PORT_STATIC,
|
CHANNEL_CANCEL_PORT_STATIC,
|
||||||
options.gateway_ports) > 0;
|
&options.fwd_opts) > 0;
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
logit("Unkown port forwarding.");
|
logit("Unkown port forwarding.");
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -977,16 +966,13 @@ process_cmdline(void)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (local || dynamic) {
|
if (local || dynamic) {
|
||||||
if (!channel_setup_local_fwd_listener(fwd.listen_host,
|
if (!channel_setup_local_fwd_listener(&fwd,
|
||||||
fwd.listen_port, fwd.connect_host,
|
&options.fwd_opts)) {
|
||||||
fwd.connect_port, options.gateway_ports)) {
|
|
||||||
logit("Port forwarding failed.");
|
logit("Port forwarding failed.");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (channel_request_remote_forwarding(fwd.listen_host,
|
if (channel_request_remote_forwarding(&fwd) < 0) {
|
||||||
fwd.listen_port, fwd.connect_host,
|
|
||||||
fwd.connect_port) < 0) {
|
|
||||||
logit("Port forwarding failed.");
|
logit("Port forwarding failed.");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -999,7 +985,9 @@ out:
|
||||||
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
|
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
free(fwd.listen_host);
|
free(fwd.listen_host);
|
||||||
|
free(fwd.listen_path);
|
||||||
free(fwd.connect_host);
|
free(fwd.connect_host);
|
||||||
|
free(fwd.connect_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reasons to suppress output of an escape command in help output */
|
/* reasons to suppress output of an escape command in help output */
|
||||||
|
@ -1845,9 +1833,8 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
|
||||||
originator_port = packet_get_int();
|
originator_port = packet_get_int();
|
||||||
packet_check_eom();
|
packet_check_eom();
|
||||||
|
|
||||||
debug("client_request_forwarded_tcpip: listen %s port %d, "
|
debug("%s: listen %s port %d, originator %s port %d", __func__,
|
||||||
"originator %s port %d", listen_address, listen_port,
|
listen_address, listen_port, originator_address, originator_port);
|
||||||
originator_address, originator_port);
|
|
||||||
|
|
||||||
c = channel_connect_by_listen_address(listen_address, listen_port,
|
c = channel_connect_by_listen_address(listen_address, listen_port,
|
||||||
"forwarded-tcpip", originator_address);
|
"forwarded-tcpip", originator_address);
|
||||||
|
@ -1857,6 +1844,27 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Channel *
|
||||||
|
client_request_forwarded_streamlocal(const char *request_type, int rchan)
|
||||||
|
{
|
||||||
|
Channel *c = NULL;
|
||||||
|
char *listen_path;
|
||||||
|
|
||||||
|
/* Get the remote path. */
|
||||||
|
listen_path = packet_get_string(NULL);
|
||||||
|
/* XXX: Skip reserved field for now. */
|
||||||
|
if (packet_get_string_ptr(NULL) == NULL)
|
||||||
|
fatal("%s: packet_get_string_ptr failed", __func__);
|
||||||
|
packet_check_eom();
|
||||||
|
|
||||||
|
debug("%s: %s", __func__, listen_path);
|
||||||
|
|
||||||
|
c = channel_connect_by_listen_path(listen_path,
|
||||||
|
"forwarded-streamlocal@openssh.com", "forwarded-streamlocal");
|
||||||
|
free(listen_path);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
static Channel *
|
static Channel *
|
||||||
client_request_x11(const char *request_type, int rchan)
|
client_request_x11(const char *request_type, int rchan)
|
||||||
{
|
{
|
||||||
|
@ -1984,6 +1992,8 @@ client_input_channel_open(int type, u_int32_t seq, void *ctxt)
|
||||||
|
|
||||||
if (strcmp(ctype, "forwarded-tcpip") == 0) {
|
if (strcmp(ctype, "forwarded-tcpip") == 0) {
|
||||||
c = client_request_forwarded_tcpip(ctype, rchan);
|
c = client_request_forwarded_tcpip(ctype, rchan);
|
||||||
|
} else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) {
|
||||||
|
c = client_request_forwarded_streamlocal(ctype, rchan);
|
||||||
} else if (strcmp(ctype, "x11") == 0) {
|
} else if (strcmp(ctype, "x11") == 0) {
|
||||||
c = client_request_x11(ctype, rchan);
|
c = client_request_x11(ctype, rchan);
|
||||||
} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
|
} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
|
||||||
|
|
49
misc.c
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) 2000 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
|
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
|
||||||
|
@ -29,6 +29,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -1056,6 +1057,52 @@ lowercase(char *s)
|
||||||
for (; *s; s++)
|
for (; *s; s++)
|
||||||
*s = tolower((u_char)*s);
|
*s = tolower((u_char)*s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
unix_listener(const char *path, int backlog, int unlink_first)
|
||||||
|
{
|
||||||
|
struct sockaddr_un sunaddr;
|
||||||
|
int saved_errno, sock;
|
||||||
|
|
||||||
|
memset(&sunaddr, 0, sizeof(sunaddr));
|
||||||
|
sunaddr.sun_family = AF_UNIX;
|
||||||
|
if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) {
|
||||||
|
error("%s: \"%s\" too long for Unix domain socket", __func__,
|
||||||
|
path);
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sock = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (sock < 0) {
|
||||||
|
saved_errno = errno;
|
||||||
|
error("socket: %.100s", strerror(errno));
|
||||||
|
errno = saved_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (unlink_first == 1) {
|
||||||
|
if (unlink(path) != 0 && errno != ENOENT)
|
||||||
|
error("unlink(%s): %.100s", path, strerror(errno));
|
||||||
|
}
|
||||||
|
if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
|
||||||
|
saved_errno = errno;
|
||||||
|
error("bind: %.100s", strerror(errno));
|
||||||
|
close(sock);
|
||||||
|
error("%s: cannot bind to path: %s", __func__, path);
|
||||||
|
errno = saved_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (listen(sock, backlog) < 0) {
|
||||||
|
saved_errno = errno;
|
||||||
|
error("listen: %.100s", strerror(errno));
|
||||||
|
close(sock);
|
||||||
|
unlink(path);
|
||||||
|
error("%s: cannot listen on path: %s", __func__, path);
|
||||||
|
errno = saved_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
void
|
void
|
||||||
sock_set_v6only(int s)
|
sock_set_v6only(int s)
|
||||||
{
|
{
|
||||||
|
|
25
misc.h
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -15,6 +15,25 @@
|
||||||
#ifndef _MISC_H
|
#ifndef _MISC_H
|
||||||
#define _MISC_H
|
#define _MISC_H
|
||||||
|
|
||||||
|
/* Data structure for representing a forwarding request. */
|
||||||
|
struct Forward {
|
||||||
|
char *listen_host; /* Host (address) to listen on. */
|
||||||
|
int listen_port; /* Port to forward. */
|
||||||
|
char *listen_path; /* Path to bind domain socket. */
|
||||||
|
char *connect_host; /* Host to connect. */
|
||||||
|
int connect_port; /* Port to connect on connect_host. */
|
||||||
|
char *connect_path; /* Path to connect domain socket. */
|
||||||
|
int allocated_port; /* Dynamically allocated listen port */
|
||||||
|
int handle; /* Handle for dynamic listen ports */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Common server and client forwarding options. */
|
||||||
|
struct ForwardOptions {
|
||||||
|
int gateway_ports; /* Allow remote connects to forwarded ports. */
|
||||||
|
mode_t streamlocal_bind_mask; /* umask for streamlocal binds */
|
||||||
|
int streamlocal_bind_unlink; /* unlink socket before bind */
|
||||||
|
};
|
||||||
|
|
||||||
/* misc.c */
|
/* misc.c */
|
||||||
|
|
||||||
char *chop(char *);
|
char *chop(char *);
|
||||||
|
@ -37,6 +56,7 @@ void ms_subtract_diff(struct timeval *, int *);
|
||||||
void ms_to_timeval(struct timeval *, int);
|
void ms_to_timeval(struct timeval *, int);
|
||||||
time_t monotime(void);
|
time_t monotime(void);
|
||||||
void lowercase(char *s);
|
void lowercase(char *s);
|
||||||
|
int unix_listener(const char *, int, int);
|
||||||
|
|
||||||
void sock_set_v6only(int);
|
void sock_set_v6only(int);
|
||||||
|
|
||||||
|
@ -68,6 +88,9 @@ int tun_open(int, int);
|
||||||
#define SSH_TUNID_ERR (SSH_TUNID_ANY - 1)
|
#define SSH_TUNID_ERR (SSH_TUNID_ANY - 1)
|
||||||
#define SSH_TUNID_MAX (SSH_TUNID_ANY - 2)
|
#define SSH_TUNID_MAX (SSH_TUNID_ANY - 2)
|
||||||
|
|
||||||
|
/* Fake port to indicate that host field is really a path. */
|
||||||
|
#define PORT_STREAMLOCAL -2
|
||||||
|
|
||||||
/* Functions to extract or store big-endian words of various sizes */
|
/* Functions to extract or store big-endian words of various sizes */
|
||||||
u_int64_t get_u64(const void *)
|
u_int64_t get_u64(const void *)
|
||||||
__attribute__((__bounded__( __minbytes__, 1, 8)));
|
__attribute__((__bounded__( __minbytes__, 1, 8)));
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: monitor.c,v 1.134 2014/06/24 01:13:21 djm Exp $ */
|
/* $OpenBSD: monitor.c,v 1.135 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||||
|
@ -87,6 +87,7 @@
|
||||||
#include "sshlogin.h"
|
#include "sshlogin.h"
|
||||||
#include "canohost.h"
|
#include "canohost.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "monitor.h"
|
#include "monitor.h"
|
||||||
#include "monitor_mm.h"
|
#include "monitor_mm.h"
|
||||||
|
@ -95,7 +96,6 @@
|
||||||
#endif
|
#endif
|
||||||
#include "monitor_wrap.h"
|
#include "monitor_wrap.h"
|
||||||
#include "monitor_fdpass.h"
|
#include "monitor_fdpass.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "ssh2.h"
|
#include "ssh2.h"
|
||||||
#include "roaming.h"
|
#include "roaming.h"
|
||||||
|
|
203
mux.c
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>
|
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
|
||||||
*
|
*
|
||||||
|
@ -509,29 +509,33 @@ process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
format_forward(u_int ftype, Forward *fwd)
|
format_forward(u_int ftype, struct Forward *fwd)
|
||||||
{
|
{
|
||||||
char *ret;
|
char *ret;
|
||||||
|
|
||||||
switch (ftype) {
|
switch (ftype) {
|
||||||
case MUX_FWD_LOCAL:
|
case MUX_FWD_LOCAL:
|
||||||
xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d",
|
xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d",
|
||||||
|
(fwd->listen_path != NULL) ? fwd->listen_path :
|
||||||
(fwd->listen_host == NULL) ?
|
(fwd->listen_host == NULL) ?
|
||||||
(options.gateway_ports ? "*" : "LOCALHOST") :
|
(options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
|
||||||
fwd->listen_host, fwd->listen_port,
|
fwd->listen_host, fwd->listen_port,
|
||||||
|
(fwd->connect_path != NULL) ? fwd->connect_path :
|
||||||
fwd->connect_host, fwd->connect_port);
|
fwd->connect_host, fwd->connect_port);
|
||||||
break;
|
break;
|
||||||
case MUX_FWD_DYNAMIC:
|
case MUX_FWD_DYNAMIC:
|
||||||
xasprintf(&ret, "dynamic forward %.200s:%d -> *",
|
xasprintf(&ret, "dynamic forward %.200s:%d -> *",
|
||||||
(fwd->listen_host == NULL) ?
|
(fwd->listen_host == NULL) ?
|
||||||
(options.gateway_ports ? "*" : "LOCALHOST") :
|
(options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
|
||||||
fwd->listen_host, fwd->listen_port);
|
fwd->listen_host, fwd->listen_port);
|
||||||
break;
|
break;
|
||||||
case MUX_FWD_REMOTE:
|
case MUX_FWD_REMOTE:
|
||||||
xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d",
|
xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d",
|
||||||
|
(fwd->listen_path != NULL) ? fwd->listen_path :
|
||||||
(fwd->listen_host == NULL) ?
|
(fwd->listen_host == NULL) ?
|
||||||
"LOCALHOST" : fwd->listen_host,
|
"LOCALHOST" : fwd->listen_host,
|
||||||
fwd->listen_port,
|
fwd->listen_port,
|
||||||
|
(fwd->connect_path != NULL) ? fwd->connect_path :
|
||||||
fwd->connect_host, fwd->connect_port);
|
fwd->connect_host, fwd->connect_port);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -551,14 +555,18 @@ compare_host(const char *a, const char *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compare_forward(Forward *a, Forward *b)
|
compare_forward(struct Forward *a, struct Forward *b)
|
||||||
{
|
{
|
||||||
if (!compare_host(a->listen_host, b->listen_host))
|
if (!compare_host(a->listen_host, b->listen_host))
|
||||||
return 0;
|
return 0;
|
||||||
|
if (!compare_host(a->listen_path, b->listen_path))
|
||||||
|
return 0;
|
||||||
if (a->listen_port != b->listen_port)
|
if (a->listen_port != b->listen_port)
|
||||||
return 0;
|
return 0;
|
||||||
if (!compare_host(a->connect_host, b->connect_host))
|
if (!compare_host(a->connect_host, b->connect_host))
|
||||||
return 0;
|
return 0;
|
||||||
|
if (!compare_host(a->connect_path, b->connect_path))
|
||||||
|
return 0;
|
||||||
if (a->connect_port != b->connect_port)
|
if (a->connect_port != b->connect_port)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -570,7 +578,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
||||||
{
|
{
|
||||||
struct mux_channel_confirm_ctx *fctx = ctxt;
|
struct mux_channel_confirm_ctx *fctx = ctxt;
|
||||||
char *failmsg = NULL;
|
char *failmsg = NULL;
|
||||||
Forward *rfwd;
|
struct Forward *rfwd;
|
||||||
Channel *c;
|
Channel *c;
|
||||||
Buffer out;
|
Buffer out;
|
||||||
|
|
||||||
|
@ -587,7 +595,8 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
||||||
rfwd = &options.remote_forwards[fctx->fid];
|
rfwd = &options.remote_forwards[fctx->fid];
|
||||||
debug("%s: %s for: listen %d, connect %s:%d", __func__,
|
debug("%s: %s for: listen %d, connect %s:%d", __func__,
|
||||||
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
|
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
|
||||||
rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
|
rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
|
||||||
|
rfwd->connect_host, rfwd->connect_port);
|
||||||
if (type == SSH2_MSG_REQUEST_SUCCESS) {
|
if (type == SSH2_MSG_REQUEST_SUCCESS) {
|
||||||
if (rfwd->listen_port == 0) {
|
if (rfwd->listen_port == 0) {
|
||||||
rfwd->allocated_port = packet_get_int();
|
rfwd->allocated_port = packet_get_int();
|
||||||
|
@ -607,8 +616,12 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
||||||
} else {
|
} else {
|
||||||
if (rfwd->listen_port == 0)
|
if (rfwd->listen_port == 0)
|
||||||
channel_update_permitted_opens(rfwd->handle, -1);
|
channel_update_permitted_opens(rfwd->handle, -1);
|
||||||
xasprintf(&failmsg, "remote port forwarding failed for "
|
if (rfwd->listen_path != NULL)
|
||||||
"listen port %d", rfwd->listen_port);
|
xasprintf(&failmsg, "remote port forwarding failed for "
|
||||||
|
"listen path %s", rfwd->listen_path);
|
||||||
|
else
|
||||||
|
xasprintf(&failmsg, "remote port forwarding failed for "
|
||||||
|
"listen port %d", rfwd->listen_port);
|
||||||
}
|
}
|
||||||
fail:
|
fail:
|
||||||
error("%s: %s", __func__, failmsg);
|
error("%s: %s", __func__, failmsg);
|
||||||
|
@ -627,33 +640,45 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
||||||
static int
|
static int
|
||||||
process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||||
{
|
{
|
||||||
Forward fwd;
|
struct Forward fwd;
|
||||||
char *fwd_desc = NULL;
|
char *fwd_desc = NULL;
|
||||||
|
char *listen_addr, *connect_addr;
|
||||||
u_int ftype;
|
u_int ftype;
|
||||||
u_int lport, cport;
|
u_int lport, cport;
|
||||||
int i, ret = 0, freefwd = 1;
|
int i, ret = 0, freefwd = 1;
|
||||||
|
|
||||||
fwd.listen_host = fwd.connect_host = NULL;
|
/* XXX - lport/cport check redundant */
|
||||||
if (buffer_get_int_ret(&ftype, m) != 0 ||
|
if (buffer_get_int_ret(&ftype, m) != 0 ||
|
||||||
(fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL ||
|
(listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
|
||||||
buffer_get_int_ret(&lport, m) != 0 ||
|
buffer_get_int_ret(&lport, m) != 0 ||
|
||||||
(fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL ||
|
(connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
|
||||||
buffer_get_int_ret(&cport, m) != 0 ||
|
buffer_get_int_ret(&cport, m) != 0 ||
|
||||||
lport > 65535 || cport > 65535) {
|
(lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
|
||||||
|
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
|
||||||
error("%s: malformed message", __func__);
|
error("%s: malformed message", __func__);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (*listen_addr == '\0') {
|
||||||
|
free(listen_addr);
|
||||||
|
listen_addr = NULL;
|
||||||
|
}
|
||||||
|
if (*connect_addr == '\0') {
|
||||||
|
free(connect_addr);
|
||||||
|
connect_addr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&fwd, 0, sizeof(fwd));
|
||||||
fwd.listen_port = lport;
|
fwd.listen_port = lport;
|
||||||
|
if (fwd.listen_port == PORT_STREAMLOCAL)
|
||||||
|
fwd.listen_path = listen_addr;
|
||||||
|
else
|
||||||
|
fwd.listen_host = listen_addr;
|
||||||
fwd.connect_port = cport;
|
fwd.connect_port = cport;
|
||||||
if (*fwd.listen_host == '\0') {
|
if (fwd.connect_port == PORT_STREAMLOCAL)
|
||||||
free(fwd.listen_host);
|
fwd.connect_path = connect_addr;
|
||||||
fwd.listen_host = NULL;
|
else
|
||||||
}
|
fwd.connect_host = connect_addr;
|
||||||
if (*fwd.connect_host == '\0') {
|
|
||||||
free(fwd.connect_host);
|
|
||||||
fwd.connect_host = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug2("%s: channel %d: request %s", __func__, c->self,
|
debug2("%s: channel %d: request %s", __func__, c->self,
|
||||||
(fwd_desc = format_forward(ftype, &fwd)));
|
(fwd_desc = format_forward(ftype, &fwd)));
|
||||||
|
@ -662,25 +687,30 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||||
ftype != MUX_FWD_DYNAMIC) {
|
ftype != MUX_FWD_DYNAMIC) {
|
||||||
logit("%s: invalid forwarding type %u", __func__, ftype);
|
logit("%s: invalid forwarding type %u", __func__, ftype);
|
||||||
invalid:
|
invalid:
|
||||||
free(fwd.listen_host);
|
free(listen_addr);
|
||||||
free(fwd.connect_host);
|
free(connect_addr);
|
||||||
buffer_put_int(r, MUX_S_FAILURE);
|
buffer_put_int(r, MUX_S_FAILURE);
|
||||||
buffer_put_int(r, rid);
|
buffer_put_int(r, rid);
|
||||||
buffer_put_cstring(r, "Invalid forwarding request");
|
buffer_put_cstring(r, "Invalid forwarding request");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (fwd.listen_port >= 65536) {
|
if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) {
|
||||||
|
logit("%s: streamlocal and dynamic forwards "
|
||||||
|
"are mutually exclusive", __func__);
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) {
|
||||||
logit("%s: invalid listen port %u", __func__,
|
logit("%s: invalid listen port %u", __func__,
|
||||||
fwd.listen_port);
|
fwd.listen_port);
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
if (fwd.connect_port >= 65536 || (ftype != MUX_FWD_DYNAMIC &&
|
if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536)
|
||||||
ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) {
|
|| (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) {
|
||||||
logit("%s: invalid connect port %u", __func__,
|
logit("%s: invalid connect port %u", __func__,
|
||||||
fwd.connect_port);
|
fwd.connect_port);
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL) {
|
if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) {
|
||||||
logit("%s: missing connect host", __func__);
|
logit("%s: missing connect host", __func__);
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
|
@ -731,9 +761,8 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
|
if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
|
||||||
if (!channel_setup_local_fwd_listener(fwd.listen_host,
|
if (!channel_setup_local_fwd_listener(&fwd,
|
||||||
fwd.listen_port, fwd.connect_host, fwd.connect_port,
|
&options.fwd_opts)) {
|
||||||
options.gateway_ports)) {
|
|
||||||
fail:
|
fail:
|
||||||
logit("slave-requested %s failed", fwd_desc);
|
logit("slave-requested %s failed", fwd_desc);
|
||||||
buffer_put_int(r, MUX_S_FAILURE);
|
buffer_put_int(r, MUX_S_FAILURE);
|
||||||
|
@ -746,8 +775,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||||
} else {
|
} else {
|
||||||
struct mux_channel_confirm_ctx *fctx;
|
struct mux_channel_confirm_ctx *fctx;
|
||||||
|
|
||||||
fwd.handle = channel_request_remote_forwarding(fwd.listen_host,
|
fwd.handle = channel_request_remote_forwarding(&fwd);
|
||||||
fwd.listen_port, fwd.connect_host, fwd.connect_port);
|
|
||||||
if (fwd.handle < 0)
|
if (fwd.handle < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
add_remote_forward(&options, &fwd);
|
add_remote_forward(&options, &fwd);
|
||||||
|
@ -768,7 +796,9 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||||
free(fwd_desc);
|
free(fwd_desc);
|
||||||
if (freefwd) {
|
if (freefwd) {
|
||||||
free(fwd.listen_host);
|
free(fwd.listen_host);
|
||||||
|
free(fwd.listen_path);
|
||||||
free(fwd.connect_host);
|
free(fwd.connect_host);
|
||||||
|
free(fwd.connect_path);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -776,36 +806,47 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||||
static int
|
static int
|
||||||
process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||||
{
|
{
|
||||||
Forward fwd, *found_fwd;
|
struct Forward fwd, *found_fwd;
|
||||||
char *fwd_desc = NULL;
|
char *fwd_desc = NULL;
|
||||||
const char *error_reason = NULL;
|
const char *error_reason = NULL;
|
||||||
|
char *listen_addr = NULL, *connect_addr = NULL;
|
||||||
u_int ftype;
|
u_int ftype;
|
||||||
int i, listen_port, ret = 0;
|
int i, ret = 0;
|
||||||
u_int lport, cport;
|
u_int lport, cport;
|
||||||
|
|
||||||
fwd.listen_host = fwd.connect_host = NULL;
|
|
||||||
if (buffer_get_int_ret(&ftype, m) != 0 ||
|
if (buffer_get_int_ret(&ftype, m) != 0 ||
|
||||||
(fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL ||
|
(listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
|
||||||
buffer_get_int_ret(&lport, m) != 0 ||
|
buffer_get_int_ret(&lport, m) != 0 ||
|
||||||
(fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL ||
|
(connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
|
||||||
buffer_get_int_ret(&cport, m) != 0 ||
|
buffer_get_int_ret(&cport, m) != 0 ||
|
||||||
lport > 65535 || cport > 65535) {
|
(lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
|
||||||
|
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
|
||||||
error("%s: malformed message", __func__);
|
error("%s: malformed message", __func__);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
fwd.listen_port = lport;
|
|
||||||
fwd.connect_port = cport;
|
|
||||||
|
|
||||||
if (*fwd.listen_host == '\0') {
|
if (*listen_addr == '\0') {
|
||||||
free(fwd.listen_host);
|
free(listen_addr);
|
||||||
fwd.listen_host = NULL;
|
listen_addr = NULL;
|
||||||
}
|
}
|
||||||
if (*fwd.connect_host == '\0') {
|
if (*connect_addr == '\0') {
|
||||||
free(fwd.connect_host);
|
free(connect_addr);
|
||||||
fwd.connect_host = NULL;
|
connect_addr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(&fwd, 0, sizeof(fwd));
|
||||||
|
fwd.listen_port = lport;
|
||||||
|
if (fwd.listen_port == PORT_STREAMLOCAL)
|
||||||
|
fwd.listen_path = listen_addr;
|
||||||
|
else
|
||||||
|
fwd.listen_host = listen_addr;
|
||||||
|
fwd.connect_port = cport;
|
||||||
|
if (fwd.connect_port == PORT_STREAMLOCAL)
|
||||||
|
fwd.connect_path = connect_addr;
|
||||||
|
else
|
||||||
|
fwd.connect_host = connect_addr;
|
||||||
|
|
||||||
debug2("%s: channel %d: request cancel %s", __func__, c->self,
|
debug2("%s: channel %d: request cancel %s", __func__, c->self,
|
||||||
(fwd_desc = format_forward(ftype, &fwd)));
|
(fwd_desc = format_forward(ftype, &fwd)));
|
||||||
|
|
||||||
|
@ -840,18 +881,14 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||||
* This shouldn't fail unless we confused the host/port
|
* This shouldn't fail unless we confused the host/port
|
||||||
* between options.remote_forwards and permitted_opens.
|
* between options.remote_forwards and permitted_opens.
|
||||||
* However, for dynamic allocated listen ports we need
|
* However, for dynamic allocated listen ports we need
|
||||||
* to lookup the actual listen port.
|
* to use the actual listen port.
|
||||||
*/
|
*/
|
||||||
listen_port = (fwd.listen_port == 0) ?
|
if (channel_request_rforward_cancel(found_fwd) == -1)
|
||||||
found_fwd->allocated_port : fwd.listen_port;
|
|
||||||
if (channel_request_rforward_cancel(fwd.listen_host,
|
|
||||||
listen_port) == -1)
|
|
||||||
error_reason = "port not in permitted opens";
|
error_reason = "port not in permitted opens";
|
||||||
} else { /* local and dynamic forwards */
|
} else { /* local and dynamic forwards */
|
||||||
/* Ditto */
|
/* Ditto */
|
||||||
if (channel_cancel_lport_listener(fwd.listen_host,
|
if (channel_cancel_lport_listener(&fwd, fwd.connect_port,
|
||||||
fwd.listen_port, fwd.connect_port,
|
&options.fwd_opts) == -1)
|
||||||
options.gateway_ports) == -1)
|
|
||||||
error_reason = "port not found";
|
error_reason = "port not found";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -860,8 +897,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||||
buffer_put_int(r, rid);
|
buffer_put_int(r, rid);
|
||||||
|
|
||||||
free(found_fwd->listen_host);
|
free(found_fwd->listen_host);
|
||||||
|
free(found_fwd->listen_path);
|
||||||
free(found_fwd->connect_host);
|
free(found_fwd->connect_host);
|
||||||
|
free(found_fwd->connect_path);
|
||||||
found_fwd->listen_host = found_fwd->connect_host = NULL;
|
found_fwd->listen_host = found_fwd->connect_host = NULL;
|
||||||
|
found_fwd->listen_path = found_fwd->connect_path = NULL;
|
||||||
found_fwd->listen_port = found_fwd->connect_port = 0;
|
found_fwd->listen_port = found_fwd->connect_port = 0;
|
||||||
} else {
|
} else {
|
||||||
buffer_put_int(r, MUX_S_FAILURE);
|
buffer_put_int(r, MUX_S_FAILURE);
|
||||||
|
@ -870,8 +910,8 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
free(fwd_desc);
|
free(fwd_desc);
|
||||||
free(fwd.listen_host);
|
free(listen_addr);
|
||||||
free(fwd.connect_host);
|
free(connect_addr);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1133,8 +1173,6 @@ mux_tty_alloc_failed(Channel *c)
|
||||||
void
|
void
|
||||||
muxserver_listen(void)
|
muxserver_listen(void)
|
||||||
{
|
{
|
||||||
struct sockaddr_un addr;
|
|
||||||
socklen_t sun_len;
|
|
||||||
mode_t old_umask;
|
mode_t old_umask;
|
||||||
char *orig_control_path = options.control_path;
|
char *orig_control_path = options.control_path;
|
||||||
char rbuf[16+1];
|
char rbuf[16+1];
|
||||||
|
@ -1163,23 +1201,10 @@ muxserver_listen(void)
|
||||||
xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf);
|
xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf);
|
||||||
debug3("%s: temporary control path %s", __func__, options.control_path);
|
debug3("%s: temporary control path %s", __func__, options.control_path);
|
||||||
|
|
||||||
memset(&addr, '\0', sizeof(addr));
|
|
||||||
addr.sun_family = AF_UNIX;
|
|
||||||
sun_len = offsetof(struct sockaddr_un, sun_path) +
|
|
||||||
strlen(options.control_path) + 1;
|
|
||||||
|
|
||||||
if (strlcpy(addr.sun_path, options.control_path,
|
|
||||||
sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) {
|
|
||||||
error("ControlPath \"%s\" too long for Unix domain socket",
|
|
||||||
options.control_path);
|
|
||||||
goto disable_mux_master;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
|
|
||||||
fatal("%s socket(): %s", __func__, strerror(errno));
|
|
||||||
|
|
||||||
old_umask = umask(0177);
|
old_umask = umask(0177);
|
||||||
if (bind(muxserver_sock, (struct sockaddr *)&addr, sun_len) == -1) {
|
muxserver_sock = unix_listener(options.control_path, 64, 0);
|
||||||
|
umask(old_umask);
|
||||||
|
if (muxserver_sock < 0) {
|
||||||
if (errno == EINVAL || errno == EADDRINUSE) {
|
if (errno == EINVAL || errno == EADDRINUSE) {
|
||||||
error("ControlSocket %s already exists, "
|
error("ControlSocket %s already exists, "
|
||||||
"disabling multiplexing", options.control_path);
|
"disabling multiplexing", options.control_path);
|
||||||
|
@ -1193,13 +1218,11 @@ muxserver_listen(void)
|
||||||
options.control_path = NULL;
|
options.control_path = NULL;
|
||||||
options.control_master = SSHCTL_MASTER_NO;
|
options.control_master = SSHCTL_MASTER_NO;
|
||||||
return;
|
return;
|
||||||
} else
|
} else {
|
||||||
fatal("%s bind(): %s", __func__, strerror(errno));
|
/* unix_listener() logs the error */
|
||||||
|
cleanup_exit(255);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
umask(old_umask);
|
|
||||||
|
|
||||||
if (listen(muxserver_sock, 64) == -1)
|
|
||||||
fatal("%s listen(): %s", __func__, strerror(errno));
|
|
||||||
|
|
||||||
/* Now atomically "move" the mux socket into position */
|
/* Now atomically "move" the mux socket into position */
|
||||||
if (link(options.control_path, orig_control_path) != 0) {
|
if (link(options.control_path, orig_control_path) != 0) {
|
||||||
|
@ -1593,7 +1616,7 @@ mux_client_request_terminate(int fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd)
|
mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
|
||||||
{
|
{
|
||||||
Buffer m;
|
Buffer m;
|
||||||
char *e, *fwd_desc;
|
char *e, *fwd_desc;
|
||||||
|
@ -1608,11 +1631,19 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd)
|
||||||
buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD);
|
buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD);
|
||||||
buffer_put_int(&m, muxclient_request_id);
|
buffer_put_int(&m, muxclient_request_id);
|
||||||
buffer_put_int(&m, ftype);
|
buffer_put_int(&m, ftype);
|
||||||
buffer_put_cstring(&m,
|
if (fwd->listen_path != NULL) {
|
||||||
fwd->listen_host == NULL ? "" : fwd->listen_host);
|
buffer_put_cstring(&m, fwd->listen_path);
|
||||||
|
} else {
|
||||||
|
buffer_put_cstring(&m,
|
||||||
|
fwd->listen_host == NULL ? "" : fwd->listen_host);
|
||||||
|
}
|
||||||
buffer_put_int(&m, fwd->listen_port);
|
buffer_put_int(&m, fwd->listen_port);
|
||||||
buffer_put_cstring(&m,
|
if (fwd->connect_path != NULL) {
|
||||||
fwd->connect_host == NULL ? "" : fwd->connect_host);
|
buffer_put_cstring(&m, fwd->connect_path);
|
||||||
|
} else {
|
||||||
|
buffer_put_cstring(&m,
|
||||||
|
fwd->connect_host == NULL ? "" : fwd->connect_host);
|
||||||
|
}
|
||||||
buffer_put_int(&m, fwd->connect_port);
|
buffer_put_int(&m, fwd->connect_port);
|
||||||
|
|
||||||
if (mux_client_write_packet(fd, &m) != 0)
|
if (mux_client_write_packet(fd, &m) != 0)
|
||||||
|
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -66,7 +66,6 @@
|
||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
#include "compress.h"
|
#include "compress.h"
|
||||||
#include "deattack.h"
|
#include "deattack.h"
|
||||||
#include "channels.h"
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "ssh1.h"
|
#include "ssh1.h"
|
||||||
#include "ssh2.h"
|
#include "ssh2.h"
|
||||||
|
@ -77,6 +76,7 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "canohost.h"
|
#include "canohost.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "channels.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "ssherr.h"
|
#include "ssherr.h"
|
||||||
#include "roaming.h"
|
#include "roaming.h"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: platform.c,v 1.21 2014/01/21 01:59:29 tim Exp $ */
|
/* $Id: platform.c,v 1.22 2014/07/18 04:11:26 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 Darren Tucker. All rights reserved.
|
* Copyright (c) 2006 Darren Tucker. All rights reserved.
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
|
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -18,6 +18,7 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/in_systm.h>
|
#include <netinet/in_systm.h>
|
||||||
|
@ -48,9 +49,9 @@
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "readconf.h"
|
#include "readconf.h"
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "kex.h"
|
#include "kex.h"
|
||||||
#include "mac.h"
|
#include "mac.h"
|
||||||
|
@ -149,6 +150,7 @@ typedef enum {
|
||||||
oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
|
oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
|
||||||
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
|
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
|
||||||
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
|
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
|
||||||
|
oStreamLocalBindMask, oStreamLocalBindUnlink,
|
||||||
oIgnoredUnknownOption, oDeprecated, oUnsupported
|
oIgnoredUnknownOption, oDeprecated, oUnsupported
|
||||||
} OpCodes;
|
} OpCodes;
|
||||||
|
|
||||||
|
@ -261,6 +263,8 @@ static struct {
|
||||||
{ "canonicalizehostname", oCanonicalizeHostname },
|
{ "canonicalizehostname", oCanonicalizeHostname },
|
||||||
{ "canonicalizemaxdots", oCanonicalizeMaxDots },
|
{ "canonicalizemaxdots", oCanonicalizeMaxDots },
|
||||||
{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
|
{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
|
||||||
|
{ "streamlocalbindmask", oStreamLocalBindMask },
|
||||||
|
{ "streamlocalbindunlink", oStreamLocalBindUnlink },
|
||||||
{ "ignoreunknown", oIgnoreUnknown },
|
{ "ignoreunknown", oIgnoreUnknown },
|
||||||
|
|
||||||
{ NULL, oBadOption }
|
{ NULL, oBadOption }
|
||||||
|
@ -272,12 +276,13 @@ static struct {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
add_local_forward(Options *options, const Forward *newfwd)
|
add_local_forward(Options *options, const struct Forward *newfwd)
|
||||||
{
|
{
|
||||||
Forward *fwd;
|
struct Forward *fwd;
|
||||||
#ifndef NO_IPPORT_RESERVED_CONCEPT
|
#ifndef NO_IPPORT_RESERVED_CONCEPT
|
||||||
extern uid_t original_real_uid;
|
extern uid_t original_real_uid;
|
||||||
if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0)
|
if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 &&
|
||||||
|
newfwd->listen_path == NULL)
|
||||||
fatal("Privileged ports can only be forwarded by root.");
|
fatal("Privileged ports can only be forwarded by root.");
|
||||||
#endif
|
#endif
|
||||||
options->local_forwards = xrealloc(options->local_forwards,
|
options->local_forwards = xrealloc(options->local_forwards,
|
||||||
|
@ -287,8 +292,10 @@ add_local_forward(Options *options, const Forward *newfwd)
|
||||||
|
|
||||||
fwd->listen_host = newfwd->listen_host;
|
fwd->listen_host = newfwd->listen_host;
|
||||||
fwd->listen_port = newfwd->listen_port;
|
fwd->listen_port = newfwd->listen_port;
|
||||||
|
fwd->listen_path = newfwd->listen_path;
|
||||||
fwd->connect_host = newfwd->connect_host;
|
fwd->connect_host = newfwd->connect_host;
|
||||||
fwd->connect_port = newfwd->connect_port;
|
fwd->connect_port = newfwd->connect_port;
|
||||||
|
fwd->connect_path = newfwd->connect_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -297,9 +304,9 @@ add_local_forward(Options *options, const Forward *newfwd)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
add_remote_forward(Options *options, const Forward *newfwd)
|
add_remote_forward(Options *options, const struct Forward *newfwd)
|
||||||
{
|
{
|
||||||
Forward *fwd;
|
struct Forward *fwd;
|
||||||
|
|
||||||
options->remote_forwards = xrealloc(options->remote_forwards,
|
options->remote_forwards = xrealloc(options->remote_forwards,
|
||||||
options->num_remote_forwards + 1,
|
options->num_remote_forwards + 1,
|
||||||
|
@ -308,8 +315,10 @@ add_remote_forward(Options *options, const Forward *newfwd)
|
||||||
|
|
||||||
fwd->listen_host = newfwd->listen_host;
|
fwd->listen_host = newfwd->listen_host;
|
||||||
fwd->listen_port = newfwd->listen_port;
|
fwd->listen_port = newfwd->listen_port;
|
||||||
|
fwd->listen_path = newfwd->listen_path;
|
||||||
fwd->connect_host = newfwd->connect_host;
|
fwd->connect_host = newfwd->connect_host;
|
||||||
fwd->connect_port = newfwd->connect_port;
|
fwd->connect_port = newfwd->connect_port;
|
||||||
|
fwd->connect_path = newfwd->connect_path;
|
||||||
fwd->handle = newfwd->handle;
|
fwd->handle = newfwd->handle;
|
||||||
fwd->allocated_port = 0;
|
fwd->allocated_port = 0;
|
||||||
}
|
}
|
||||||
|
@ -321,7 +330,9 @@ clear_forwardings(Options *options)
|
||||||
|
|
||||||
for (i = 0; i < options->num_local_forwards; i++) {
|
for (i = 0; i < options->num_local_forwards; i++) {
|
||||||
free(options->local_forwards[i].listen_host);
|
free(options->local_forwards[i].listen_host);
|
||||||
|
free(options->local_forwards[i].listen_path);
|
||||||
free(options->local_forwards[i].connect_host);
|
free(options->local_forwards[i].connect_host);
|
||||||
|
free(options->local_forwards[i].connect_path);
|
||||||
}
|
}
|
||||||
if (options->num_local_forwards > 0) {
|
if (options->num_local_forwards > 0) {
|
||||||
free(options->local_forwards);
|
free(options->local_forwards);
|
||||||
|
@ -330,7 +341,9 @@ clear_forwardings(Options *options)
|
||||||
options->num_local_forwards = 0;
|
options->num_local_forwards = 0;
|
||||||
for (i = 0; i < options->num_remote_forwards; i++) {
|
for (i = 0; i < options->num_remote_forwards; i++) {
|
||||||
free(options->remote_forwards[i].listen_host);
|
free(options->remote_forwards[i].listen_host);
|
||||||
|
free(options->remote_forwards[i].listen_path);
|
||||||
free(options->remote_forwards[i].connect_host);
|
free(options->remote_forwards[i].connect_host);
|
||||||
|
free(options->remote_forwards[i].connect_path);
|
||||||
}
|
}
|
||||||
if (options->num_remote_forwards > 0) {
|
if (options->num_remote_forwards > 0) {
|
||||||
free(options->remote_forwards);
|
free(options->remote_forwards);
|
||||||
|
@ -715,7 +728,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host,
|
||||||
LogLevel *log_level_ptr;
|
LogLevel *log_level_ptr;
|
||||||
long long val64;
|
long long val64;
|
||||||
size_t len;
|
size_t len;
|
||||||
Forward fwd;
|
struct Forward fwd;
|
||||||
const struct multistate *multistate_ptr;
|
const struct multistate *multistate_ptr;
|
||||||
struct allowed_cname *cname;
|
struct allowed_cname *cname;
|
||||||
|
|
||||||
|
@ -805,7 +818,7 @@ parse_time:
|
||||||
goto parse_time;
|
goto parse_time;
|
||||||
|
|
||||||
case oGatewayPorts:
|
case oGatewayPorts:
|
||||||
intptr = &options->gateway_ports;
|
intptr = &options->fwd_opts.gateway_ports;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
|
||||||
case oExitOnForwardFailure:
|
case oExitOnForwardFailure:
|
||||||
|
@ -1405,6 +1418,21 @@ parse_int:
|
||||||
intptr = &options->canonicalize_fallback_local;
|
intptr = &options->canonicalize_fallback_local;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
|
||||||
|
case oStreamLocalBindMask:
|
||||||
|
arg = strdelim(&s);
|
||||||
|
if (!arg || *arg == '\0')
|
||||||
|
fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
|
||||||
|
/* Parse mode in octal format */
|
||||||
|
value = strtol(arg, &endofnumber, 8);
|
||||||
|
if (arg == endofnumber || value < 0 || value > 0777)
|
||||||
|
fatal("%.200s line %d: Bad mask.", filename, linenum);
|
||||||
|
options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case oStreamLocalBindUnlink:
|
||||||
|
intptr = &options->fwd_opts.streamlocal_bind_unlink;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
case oDeprecated:
|
case oDeprecated:
|
||||||
debug("%s line %d: Deprecated option \"%s\"",
|
debug("%s line %d: Deprecated option \"%s\"",
|
||||||
filename, linenum, keyword);
|
filename, linenum, keyword);
|
||||||
|
@ -1502,7 +1530,9 @@ initialize_options(Options * options)
|
||||||
options->forward_x11_timeout = -1;
|
options->forward_x11_timeout = -1;
|
||||||
options->exit_on_forward_failure = -1;
|
options->exit_on_forward_failure = -1;
|
||||||
options->xauth_location = NULL;
|
options->xauth_location = NULL;
|
||||||
options->gateway_ports = -1;
|
options->fwd_opts.gateway_ports = -1;
|
||||||
|
options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
|
||||||
|
options->fwd_opts.streamlocal_bind_unlink = -1;
|
||||||
options->use_privileged_port = -1;
|
options->use_privileged_port = -1;
|
||||||
options->rsa_authentication = -1;
|
options->rsa_authentication = -1;
|
||||||
options->pubkey_authentication = -1;
|
options->pubkey_authentication = -1;
|
||||||
|
@ -1615,8 +1645,12 @@ fill_default_options(Options * options)
|
||||||
options->exit_on_forward_failure = 0;
|
options->exit_on_forward_failure = 0;
|
||||||
if (options->xauth_location == NULL)
|
if (options->xauth_location == NULL)
|
||||||
options->xauth_location = _PATH_XAUTH;
|
options->xauth_location = _PATH_XAUTH;
|
||||||
if (options->gateway_ports == -1)
|
if (options->fwd_opts.gateway_ports == -1)
|
||||||
options->gateway_ports = 0;
|
options->fwd_opts.gateway_ports = 0;
|
||||||
|
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
|
||||||
|
options->fwd_opts.streamlocal_bind_mask = 0177;
|
||||||
|
if (options->fwd_opts.streamlocal_bind_unlink == -1)
|
||||||
|
options->fwd_opts.streamlocal_bind_unlink = 0;
|
||||||
if (options->use_privileged_port == -1)
|
if (options->use_privileged_port == -1)
|
||||||
options->use_privileged_port = 0;
|
options->use_privileged_port = 0;
|
||||||
if (options->rsa_authentication == -1)
|
if (options->rsa_authentication == -1)
|
||||||
|
@ -1768,22 +1802,92 @@ fill_default_options(Options * options)
|
||||||
/* options->preferred_authentications will be set in ssh */
|
/* options->preferred_authentications will be set in ssh */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct fwdarg {
|
||||||
|
char *arg;
|
||||||
|
int ispath;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* parse_fwd_field
|
||||||
|
* parses the next field in a port forwarding specification.
|
||||||
|
* sets fwd to the parsed field and advances p past the colon
|
||||||
|
* or sets it to NULL at end of string.
|
||||||
|
* returns 0 on success, else non-zero.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
parse_fwd_field(char **p, struct fwdarg *fwd)
|
||||||
|
{
|
||||||
|
char *ep, *cp = *p;
|
||||||
|
int ispath = 0;
|
||||||
|
|
||||||
|
if (*cp == '\0') {
|
||||||
|
*p = NULL;
|
||||||
|
return -1; /* end of string */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A field escaped with square brackets is used literally.
|
||||||
|
* XXX - allow ']' to be escaped via backslash?
|
||||||
|
*/
|
||||||
|
if (*cp == '[') {
|
||||||
|
/* find matching ']' */
|
||||||
|
for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
|
||||||
|
if (*ep == '/')
|
||||||
|
ispath = 1;
|
||||||
|
}
|
||||||
|
/* no matching ']' or not at end of field. */
|
||||||
|
if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
|
||||||
|
return -1;
|
||||||
|
/* NUL terminate the field and advance p past the colon */
|
||||||
|
*ep++ = '\0';
|
||||||
|
if (*ep != '\0')
|
||||||
|
*ep++ = '\0';
|
||||||
|
fwd->arg = cp + 1;
|
||||||
|
fwd->ispath = ispath;
|
||||||
|
*p = ep;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (cp = *p; *cp != '\0'; cp++) {
|
||||||
|
switch (*cp) {
|
||||||
|
case '\\':
|
||||||
|
memmove(cp, cp + 1, strlen(cp + 1) + 1);
|
||||||
|
cp++;
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
ispath = 1;
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
*cp++ = '\0';
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
fwd->arg = *p;
|
||||||
|
fwd->ispath = ispath;
|
||||||
|
*p = cp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* parse_forward
|
* parse_forward
|
||||||
* parses a string containing a port forwarding specification of the form:
|
* parses a string containing a port forwarding specification of the form:
|
||||||
* dynamicfwd == 0
|
* dynamicfwd == 0
|
||||||
* [listenhost:]listenport:connecthost:connectport
|
* [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
|
||||||
|
* listenpath:connectpath
|
||||||
* dynamicfwd == 1
|
* dynamicfwd == 1
|
||||||
* [listenhost:]listenport
|
* [listenhost:]listenport
|
||||||
* returns number of arguments parsed or zero on error
|
* returns number of arguments parsed or zero on error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
|
parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
|
||||||
{
|
{
|
||||||
|
struct fwdarg fwdargs[4];
|
||||||
|
char *p, *cp;
|
||||||
int i;
|
int i;
|
||||||
char *p, *cp, *fwdarg[4];
|
|
||||||
|
|
||||||
memset(fwd, '\0', sizeof(*fwd));
|
memset(fwd, 0, sizeof(*fwd));
|
||||||
|
memset(fwdargs, 0, sizeof(fwdargs));
|
||||||
|
|
||||||
cp = p = xstrdup(fwdspec);
|
cp = p = xstrdup(fwdspec);
|
||||||
|
|
||||||
|
@ -1791,39 +1895,70 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
|
||||||
while (isspace((u_char)*cp))
|
while (isspace((u_char)*cp))
|
||||||
cp++;
|
cp++;
|
||||||
|
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i) {
|
||||||
if ((fwdarg[i] = hpdelim(&cp)) == NULL)
|
if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for trailing garbage */
|
/* Check for trailing garbage */
|
||||||
if (cp != NULL)
|
if (cp != NULL && *cp != '\0') {
|
||||||
i = 0; /* failure */
|
i = 0; /* failure */
|
||||||
|
}
|
||||||
|
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 1:
|
case 1:
|
||||||
fwd->listen_host = NULL;
|
if (fwdargs[0].ispath) {
|
||||||
fwd->listen_port = a2port(fwdarg[0]);
|
fwd->listen_path = xstrdup(fwdargs[0].arg);
|
||||||
|
fwd->listen_port = PORT_STREAMLOCAL;
|
||||||
|
} else {
|
||||||
|
fwd->listen_host = NULL;
|
||||||
|
fwd->listen_port = a2port(fwdargs[0].arg);
|
||||||
|
}
|
||||||
fwd->connect_host = xstrdup("socks");
|
fwd->connect_host = xstrdup("socks");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
|
if (fwdargs[0].ispath && fwdargs[1].ispath) {
|
||||||
fwd->listen_port = a2port(fwdarg[1]);
|
fwd->listen_path = xstrdup(fwdargs[0].arg);
|
||||||
fwd->connect_host = xstrdup("socks");
|
fwd->listen_port = PORT_STREAMLOCAL;
|
||||||
|
fwd->connect_path = xstrdup(fwdargs[1].arg);
|
||||||
|
fwd->connect_port = PORT_STREAMLOCAL;
|
||||||
|
} else if (fwdargs[1].ispath) {
|
||||||
|
fwd->listen_host = NULL;
|
||||||
|
fwd->listen_port = a2port(fwdargs[0].arg);
|
||||||
|
fwd->connect_path = xstrdup(fwdargs[1].arg);
|
||||||
|
fwd->connect_port = PORT_STREAMLOCAL;
|
||||||
|
} else {
|
||||||
|
fwd->listen_host = xstrdup(fwdargs[0].arg);
|
||||||
|
fwd->listen_port = a2port(fwdargs[1].arg);
|
||||||
|
fwd->connect_host = xstrdup("socks");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
fwd->listen_host = NULL;
|
if (fwdargs[0].ispath) {
|
||||||
fwd->listen_port = a2port(fwdarg[0]);
|
fwd->listen_path = xstrdup(fwdargs[0].arg);
|
||||||
fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
|
fwd->listen_port = PORT_STREAMLOCAL;
|
||||||
fwd->connect_port = a2port(fwdarg[2]);
|
fwd->connect_host = xstrdup(fwdargs[1].arg);
|
||||||
|
fwd->connect_port = a2port(fwdargs[2].arg);
|
||||||
|
} else if (fwdargs[2].ispath) {
|
||||||
|
fwd->listen_host = xstrdup(fwdargs[0].arg);
|
||||||
|
fwd->listen_port = a2port(fwdargs[1].arg);
|
||||||
|
fwd->connect_path = xstrdup(fwdargs[2].arg);
|
||||||
|
fwd->connect_port = PORT_STREAMLOCAL;
|
||||||
|
} else {
|
||||||
|
fwd->listen_host = NULL;
|
||||||
|
fwd->listen_port = a2port(fwdargs[0].arg);
|
||||||
|
fwd->connect_host = xstrdup(fwdargs[1].arg);
|
||||||
|
fwd->connect_port = a2port(fwdargs[2].arg);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
|
fwd->listen_host = xstrdup(fwdargs[0].arg);
|
||||||
fwd->listen_port = a2port(fwdarg[1]);
|
fwd->listen_port = a2port(fwdargs[1].arg);
|
||||||
fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
|
fwd->connect_host = xstrdup(fwdargs[2].arg);
|
||||||
fwd->connect_port = a2port(fwdarg[3]);
|
fwd->connect_port = a2port(fwdargs[3].arg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
i = 0; /* failure */
|
i = 0; /* failure */
|
||||||
|
@ -1835,29 +1970,42 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
|
||||||
if (!(i == 1 || i == 2))
|
if (!(i == 1 || i == 2))
|
||||||
goto fail_free;
|
goto fail_free;
|
||||||
} else {
|
} else {
|
||||||
if (!(i == 3 || i == 4))
|
if (!(i == 3 || i == 4)) {
|
||||||
goto fail_free;
|
if (fwd->connect_path == NULL &&
|
||||||
if (fwd->connect_port <= 0)
|
fwd->listen_path == NULL)
|
||||||
|
goto fail_free;
|
||||||
|
}
|
||||||
|
if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
|
||||||
goto fail_free;
|
goto fail_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
|
if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
|
||||||
|
(!remotefwd && fwd->listen_port == 0))
|
||||||
goto fail_free;
|
goto fail_free;
|
||||||
|
|
||||||
if (fwd->connect_host != NULL &&
|
if (fwd->connect_host != NULL &&
|
||||||
strlen(fwd->connect_host) >= NI_MAXHOST)
|
strlen(fwd->connect_host) >= NI_MAXHOST)
|
||||||
goto fail_free;
|
goto fail_free;
|
||||||
|
/* XXX - if connecting to a remote socket, max sun len may not match this host */
|
||||||
|
if (fwd->connect_path != NULL &&
|
||||||
|
strlen(fwd->connect_path) >= PATH_MAX_SUN)
|
||||||
|
goto fail_free;
|
||||||
if (fwd->listen_host != NULL &&
|
if (fwd->listen_host != NULL &&
|
||||||
strlen(fwd->listen_host) >= NI_MAXHOST)
|
strlen(fwd->listen_host) >= NI_MAXHOST)
|
||||||
goto fail_free;
|
goto fail_free;
|
||||||
|
if (fwd->listen_path != NULL &&
|
||||||
|
strlen(fwd->listen_path) >= PATH_MAX_SUN)
|
||||||
|
goto fail_free;
|
||||||
|
|
||||||
return (i);
|
return (i);
|
||||||
|
|
||||||
fail_free:
|
fail_free:
|
||||||
free(fwd->connect_host);
|
free(fwd->connect_host);
|
||||||
fwd->connect_host = NULL;
|
fwd->connect_host = NULL;
|
||||||
|
free(fwd->connect_path);
|
||||||
|
fwd->connect_path = NULL;
|
||||||
free(fwd->listen_host);
|
free(fwd->listen_host);
|
||||||
fwd->listen_host = NULL;
|
fwd->listen_host = NULL;
|
||||||
|
free(fwd->listen_path);
|
||||||
|
fwd->listen_path = NULL;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -16,21 +16,12 @@
|
||||||
#ifndef READCONF_H
|
#ifndef READCONF_H
|
||||||
#define READCONF_H
|
#define READCONF_H
|
||||||
|
|
||||||
/* Data structure for representing a forwarding request. */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *listen_host; /* Host (address) to listen on. */
|
|
||||||
int listen_port; /* Port to forward. */
|
|
||||||
char *connect_host; /* Host to connect. */
|
|
||||||
int connect_port; /* Port to connect on connect_host. */
|
|
||||||
int allocated_port; /* Dynamically allocated listen port */
|
|
||||||
int handle; /* Handle for dynamic listen ports */
|
|
||||||
} Forward;
|
|
||||||
/* Data structure for representing option data. */
|
/* Data structure for representing option data. */
|
||||||
|
|
||||||
#define MAX_SEND_ENV 256
|
#define MAX_SEND_ENV 256
|
||||||
#define SSH_MAX_HOSTS_FILES 32
|
#define SSH_MAX_HOSTS_FILES 32
|
||||||
#define MAX_CANON_DOMAINS 32
|
#define MAX_CANON_DOMAINS 32
|
||||||
|
#define PATH_MAX_SUN (sizeof((struct sockaddr_un *)0)->sun_path)
|
||||||
|
|
||||||
struct allowed_cname {
|
struct allowed_cname {
|
||||||
char *source_list;
|
char *source_list;
|
||||||
|
@ -44,7 +35,7 @@ typedef struct {
|
||||||
int forward_x11_trusted; /* Trust Forward X11 display. */
|
int forward_x11_trusted; /* Trust Forward X11 display. */
|
||||||
int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */
|
int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */
|
||||||
char *xauth_location; /* Location for xauth program */
|
char *xauth_location; /* Location for xauth program */
|
||||||
int gateway_ports; /* Allow remote connects to forwarded ports. */
|
struct ForwardOptions fwd_opts; /* forwarding options */
|
||||||
int use_privileged_port; /* Don't use privileged port if false. */
|
int use_privileged_port; /* Don't use privileged port if false. */
|
||||||
int rhosts_rsa_authentication; /* Try rhosts with RSA
|
int rhosts_rsa_authentication; /* Try rhosts with RSA
|
||||||
* authentication. */
|
* authentication. */
|
||||||
|
@ -106,11 +97,11 @@ typedef struct {
|
||||||
|
|
||||||
/* Local TCP/IP forward requests. */
|
/* Local TCP/IP forward requests. */
|
||||||
int num_local_forwards;
|
int num_local_forwards;
|
||||||
Forward *local_forwards;
|
struct Forward *local_forwards;
|
||||||
|
|
||||||
/* Remote TCP/IP forward requests. */
|
/* Remote TCP/IP forward requests. */
|
||||||
int num_remote_forwards;
|
int num_remote_forwards;
|
||||||
Forward *remote_forwards;
|
struct Forward *remote_forwards;
|
||||||
int clear_forwardings;
|
int clear_forwardings;
|
||||||
|
|
||||||
int enable_ssh_keysign;
|
int enable_ssh_keysign;
|
||||||
|
@ -181,12 +172,12 @@ int process_config_line(Options *, struct passwd *, const char *, char *,
|
||||||
const char *, int, int *, int);
|
const char *, int, int *, int);
|
||||||
int read_config_file(const char *, struct passwd *, const char *,
|
int read_config_file(const char *, struct passwd *, const char *,
|
||||||
Options *, int);
|
Options *, int);
|
||||||
int parse_forward(Forward *, const char *, int, int);
|
int parse_forward(struct Forward *, const char *, int, int);
|
||||||
int default_ssh_port(void);
|
int default_ssh_port(void);
|
||||||
int option_clear_or_none(const char *);
|
int option_clear_or_none(const char *);
|
||||||
|
|
||||||
void add_local_forward(Options *, const Forward *);
|
void add_local_forward(Options *, const struct Forward *);
|
||||||
void add_remote_forward(Options *, const Forward *);
|
void add_remote_forward(Options *, const struct Forward *);
|
||||||
void add_identity_file(Options *, const char *, const char *, int);
|
void add_identity_file(Options *, const char *, const char *, int);
|
||||||
|
|
||||||
#endif /* READCONF_H */
|
#endif /* READCONF_H */
|
||||||
|
|
|
@ -60,7 +60,7 @@ static const struct sandbox_policy preauth_policy[] = {
|
||||||
{ SYS___sysctl, SYSTR_POLICY_PERMIT },
|
{ SYS___sysctl, SYSTR_POLICY_PERMIT },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{ SYS_sendsyslog, SYSTR_POLICY_PERMIT },
|
// { SYS_sendsyslog, SYSTR_POLICY_PERMIT },
|
||||||
{ SYS_close, SYSTR_POLICY_PERMIT },
|
{ SYS_close, SYSTR_POLICY_PERMIT },
|
||||||
{ SYS_exit, SYSTR_POLICY_PERMIT },
|
{ SYS_exit, SYSTR_POLICY_PERMIT },
|
||||||
{ SYS_getpid, SYSTR_POLICY_PERMIT },
|
{ SYS_getpid, SYSTR_POLICY_PERMIT },
|
||||||
|
|
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
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
@ -39,10 +39,10 @@
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "kex.h"
|
#include "kex.h"
|
||||||
|
@ -120,6 +120,7 @@ initialize_server_options(ServerOptions *options)
|
||||||
options->rekey_limit = -1;
|
options->rekey_limit = -1;
|
||||||
options->rekey_interval = -1;
|
options->rekey_interval = -1;
|
||||||
options->allow_tcp_forwarding = -1;
|
options->allow_tcp_forwarding = -1;
|
||||||
|
options->allow_streamlocal_forwarding = -1;
|
||||||
options->allow_agent_forwarding = -1;
|
options->allow_agent_forwarding = -1;
|
||||||
options->num_allow_users = 0;
|
options->num_allow_users = 0;
|
||||||
options->num_deny_users = 0;
|
options->num_deny_users = 0;
|
||||||
|
@ -129,7 +130,9 @@ initialize_server_options(ServerOptions *options)
|
||||||
options->macs = NULL;
|
options->macs = NULL;
|
||||||
options->kex_algorithms = NULL;
|
options->kex_algorithms = NULL;
|
||||||
options->protocol = SSH_PROTO_UNKNOWN;
|
options->protocol = SSH_PROTO_UNKNOWN;
|
||||||
options->gateway_ports = -1;
|
options->fwd_opts.gateway_ports = -1;
|
||||||
|
options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
|
||||||
|
options->fwd_opts.streamlocal_bind_unlink = -1;
|
||||||
options->num_subsystems = 0;
|
options->num_subsystems = 0;
|
||||||
options->max_startups_begin = -1;
|
options->max_startups_begin = -1;
|
||||||
options->max_startups_rate = -1;
|
options->max_startups_rate = -1;
|
||||||
|
@ -269,10 +272,12 @@ fill_default_server_options(ServerOptions *options)
|
||||||
options->rekey_interval = 0;
|
options->rekey_interval = 0;
|
||||||
if (options->allow_tcp_forwarding == -1)
|
if (options->allow_tcp_forwarding == -1)
|
||||||
options->allow_tcp_forwarding = FORWARD_ALLOW;
|
options->allow_tcp_forwarding = FORWARD_ALLOW;
|
||||||
|
if (options->allow_streamlocal_forwarding == -1)
|
||||||
|
options->allow_streamlocal_forwarding = FORWARD_ALLOW;
|
||||||
if (options->allow_agent_forwarding == -1)
|
if (options->allow_agent_forwarding == -1)
|
||||||
options->allow_agent_forwarding = 1;
|
options->allow_agent_forwarding = 1;
|
||||||
if (options->gateway_ports == -1)
|
if (options->fwd_opts.gateway_ports == -1)
|
||||||
options->gateway_ports = 0;
|
options->fwd_opts.gateway_ports = 0;
|
||||||
if (options->max_startups == -1)
|
if (options->max_startups == -1)
|
||||||
options->max_startups = 100;
|
options->max_startups = 100;
|
||||||
if (options->max_startups_rate == -1)
|
if (options->max_startups_rate == -1)
|
||||||
|
@ -303,6 +308,10 @@ fill_default_server_options(ServerOptions *options)
|
||||||
options->ip_qos_bulk = IPTOS_THROUGHPUT;
|
options->ip_qos_bulk = IPTOS_THROUGHPUT;
|
||||||
if (options->version_addendum == NULL)
|
if (options->version_addendum == NULL)
|
||||||
options->version_addendum = xstrdup("");
|
options->version_addendum = xstrdup("");
|
||||||
|
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
|
||||||
|
options->fwd_opts.streamlocal_bind_mask = 0177;
|
||||||
|
if (options->fwd_opts.streamlocal_bind_unlink == -1)
|
||||||
|
options->fwd_opts.streamlocal_bind_unlink = 0;
|
||||||
/* Turn privilege separation on by default */
|
/* Turn privilege separation on by default */
|
||||||
if (use_privsep == -1)
|
if (use_privsep == -1)
|
||||||
use_privsep = PRIVSEP_NOSANDBOX;
|
use_privsep = PRIVSEP_NOSANDBOX;
|
||||||
|
@ -351,6 +360,8 @@ typedef enum {
|
||||||
sKexAlgorithms, sIPQoS, sVersionAddendum,
|
sKexAlgorithms, sIPQoS, sVersionAddendum,
|
||||||
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
|
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
|
||||||
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
|
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
|
||||||
|
sStreamLocalBindMask, sStreamLocalBindUnlink,
|
||||||
|
sAllowStreamLocalForwarding,
|
||||||
sDeprecated, sUnsupported
|
sDeprecated, sUnsupported
|
||||||
} ServerOpCodes;
|
} ServerOpCodes;
|
||||||
|
|
||||||
|
@ -478,6 +489,9 @@ static struct {
|
||||||
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
|
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
|
||||||
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
|
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
|
||||||
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
|
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
|
||||||
|
{ "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
|
||||||
|
{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
|
||||||
|
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
|
||||||
{ NULL, sBadOption, 0 }
|
{ NULL, sBadOption, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1195,7 +1209,7 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sGatewayPorts:
|
case sGatewayPorts:
|
||||||
intptr = &options->gateway_ports;
|
intptr = &options->fwd_opts.gateway_ports;
|
||||||
multistate_ptr = multistate_gatewayports;
|
multistate_ptr = multistate_gatewayports;
|
||||||
goto parse_multistate;
|
goto parse_multistate;
|
||||||
|
|
||||||
|
@ -1230,6 +1244,11 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||||
multistate_ptr = multistate_tcpfwd;
|
multistate_ptr = multistate_tcpfwd;
|
||||||
goto parse_multistate;
|
goto parse_multistate;
|
||||||
|
|
||||||
|
case sAllowStreamLocalForwarding:
|
||||||
|
intptr = &options->allow_streamlocal_forwarding;
|
||||||
|
multistate_ptr = multistate_tcpfwd;
|
||||||
|
goto parse_multistate;
|
||||||
|
|
||||||
case sAllowAgentForwarding:
|
case sAllowAgentForwarding:
|
||||||
intptr = &options->allow_agent_forwarding;
|
intptr = &options->allow_agent_forwarding;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
@ -1628,6 +1647,22 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case sStreamLocalBindMask:
|
||||||
|
arg = strdelim(&cp);
|
||||||
|
if (!arg || *arg == '\0')
|
||||||
|
fatal("%s line %d: missing StreamLocalBindMask argument.",
|
||||||
|
filename, linenum);
|
||||||
|
/* Parse mode in octal format */
|
||||||
|
value = strtol(arg, &p, 8);
|
||||||
|
if (arg == p || value < 0 || value > 0777)
|
||||||
|
fatal("%s line %d: Bad mask.", filename, linenum);
|
||||||
|
options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sStreamLocalBindUnlink:
|
||||||
|
intptr = &options->fwd_opts.streamlocal_bind_unlink;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
case sDeprecated:
|
case sDeprecated:
|
||||||
logit("%s line %d: Deprecated option %s",
|
logit("%s line %d: Deprecated option %s",
|
||||||
filename, linenum, arg);
|
filename, linenum, arg);
|
||||||
|
@ -1767,9 +1802,10 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
|
||||||
M_CP_INTOPT(permit_empty_passwd);
|
M_CP_INTOPT(permit_empty_passwd);
|
||||||
|
|
||||||
M_CP_INTOPT(allow_tcp_forwarding);
|
M_CP_INTOPT(allow_tcp_forwarding);
|
||||||
|
M_CP_INTOPT(allow_streamlocal_forwarding);
|
||||||
M_CP_INTOPT(allow_agent_forwarding);
|
M_CP_INTOPT(allow_agent_forwarding);
|
||||||
M_CP_INTOPT(permit_tun);
|
M_CP_INTOPT(permit_tun);
|
||||||
M_CP_INTOPT(gateway_ports);
|
M_CP_INTOPT(fwd_opts.gateway_ports);
|
||||||
M_CP_INTOPT(x11_display_offset);
|
M_CP_INTOPT(x11_display_offset);
|
||||||
M_CP_INTOPT(x11_forwarding);
|
M_CP_INTOPT(x11_forwarding);
|
||||||
M_CP_INTOPT(x11_use_localhost);
|
M_CP_INTOPT(x11_use_localhost);
|
||||||
|
@ -1867,6 +1903,8 @@ fmt_intarg(ServerOpCodes code, int val)
|
||||||
return fmt_multistate_int(val, multistate_privsep);
|
return fmt_multistate_int(val, multistate_privsep);
|
||||||
case sAllowTcpForwarding:
|
case sAllowTcpForwarding:
|
||||||
return fmt_multistate_int(val, multistate_tcpfwd);
|
return fmt_multistate_int(val, multistate_tcpfwd);
|
||||||
|
case sAllowStreamLocalForwarding:
|
||||||
|
return fmt_multistate_int(val, multistate_tcpfwd);
|
||||||
case sProtocol:
|
case sProtocol:
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case SSH_PROTO_1:
|
case SSH_PROTO_1:
|
||||||
|
@ -2023,9 +2061,10 @@ dump_config(ServerOptions *o)
|
||||||
dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
|
dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
|
||||||
dump_cfg_fmtint(sUseLogin, o->use_login);
|
dump_cfg_fmtint(sUseLogin, o->use_login);
|
||||||
dump_cfg_fmtint(sCompression, o->compression);
|
dump_cfg_fmtint(sCompression, o->compression);
|
||||||
dump_cfg_fmtint(sGatewayPorts, o->gateway_ports);
|
dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
|
||||||
dump_cfg_fmtint(sUseDNS, o->use_dns);
|
dump_cfg_fmtint(sUseDNS, o->use_dns);
|
||||||
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
|
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
|
||||||
|
dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
|
||||||
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
|
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
|
||||||
|
|
||||||
/* string arguments */
|
/* string arguments */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: servconf.h,v 1.113 2014/07/03 22:40:43 djm Exp $ */
|
/* $OpenBSD: servconf.h,v 1.114 2014/07/15 15:54:14 millert Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -92,7 +92,7 @@ typedef struct {
|
||||||
char *macs; /* Supported SSH2 macs. */
|
char *macs; /* Supported SSH2 macs. */
|
||||||
char *kex_algorithms; /* SSH2 kex methods in order of preference. */
|
char *kex_algorithms; /* SSH2 kex methods in order of preference. */
|
||||||
int protocol; /* Supported protocol versions. */
|
int protocol; /* Supported protocol versions. */
|
||||||
int gateway_ports; /* If true, allow remote connects to forwarded ports. */
|
struct ForwardOptions fwd_opts; /* forwarding options */
|
||||||
SyslogFacility log_facility; /* Facility for system logging. */
|
SyslogFacility log_facility; /* Facility for system logging. */
|
||||||
LogLevel log_level; /* Level for system logging. */
|
LogLevel log_level; /* Level for system logging. */
|
||||||
int rhosts_rsa_authentication; /* If true, permit rhosts RSA
|
int rhosts_rsa_authentication; /* If true, permit rhosts RSA
|
||||||
|
@ -124,6 +124,7 @@ typedef struct {
|
||||||
int use_login; /* If true, login(1) is used */
|
int use_login; /* If true, login(1) is used */
|
||||||
int compression; /* If true, compression is allowed */
|
int compression; /* If true, compression is allowed */
|
||||||
int allow_tcp_forwarding; /* One of FORWARD_* */
|
int allow_tcp_forwarding; /* One of FORWARD_* */
|
||||||
|
int allow_streamlocal_forwarding; /* One of FORWARD_* */
|
||||||
int allow_agent_forwarding;
|
int allow_agent_forwarding;
|
||||||
u_int num_allow_users;
|
u_int num_allow_users;
|
||||||
char *allow_users[MAX_ALLOW_USERS];
|
char *allow_users[MAX_ALLOW_USERS];
|
||||||
|
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -61,6 +61,7 @@
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "canohost.h"
|
#include "canohost.h"
|
||||||
#include "sshpty.h"
|
#include "sshpty.h"
|
||||||
|
@ -77,7 +78,6 @@
|
||||||
#include "dispatch.h"
|
#include "dispatch.h"
|
||||||
#include "auth-options.h"
|
#include "auth-options.h"
|
||||||
#include "serverloop.h"
|
#include "serverloop.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "roaming.h"
|
#include "roaming.h"
|
||||||
|
|
||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
|
@ -970,7 +970,7 @@ server_request_direct_tcpip(void)
|
||||||
/* XXX fine grained permissions */
|
/* XXX fine grained permissions */
|
||||||
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
|
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
|
||||||
!no_port_forwarding_flag) {
|
!no_port_forwarding_flag) {
|
||||||
c = channel_connect_to(target, target_port,
|
c = channel_connect_to_port(target, target_port,
|
||||||
"direct-tcpip", "direct-tcpip");
|
"direct-tcpip", "direct-tcpip");
|
||||||
} else {
|
} else {
|
||||||
logit("refused local port forward: "
|
logit("refused local port forward: "
|
||||||
|
@ -984,6 +984,38 @@ server_request_direct_tcpip(void)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Channel *
|
||||||
|
server_request_direct_streamlocal(void)
|
||||||
|
{
|
||||||
|
Channel *c = NULL;
|
||||||
|
char *target, *originator;
|
||||||
|
u_short originator_port;
|
||||||
|
|
||||||
|
target = packet_get_string(NULL);
|
||||||
|
originator = packet_get_string(NULL);
|
||||||
|
originator_port = packet_get_int();
|
||||||
|
packet_check_eom();
|
||||||
|
|
||||||
|
debug("server_request_direct_streamlocal: originator %s port %d, target %s",
|
||||||
|
originator, originator_port, target);
|
||||||
|
|
||||||
|
/* XXX fine grained permissions */
|
||||||
|
if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 &&
|
||||||
|
!no_port_forwarding_flag) {
|
||||||
|
c = channel_connect_to_path(target,
|
||||||
|
"direct-streamlocal@openssh.com", "direct-streamlocal");
|
||||||
|
} else {
|
||||||
|
logit("refused streamlocal port forward: "
|
||||||
|
"originator %s port %d, target %s",
|
||||||
|
originator, originator_port, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(originator);
|
||||||
|
free(target);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
static Channel *
|
static Channel *
|
||||||
server_request_tun(void)
|
server_request_tun(void)
|
||||||
{
|
{
|
||||||
|
@ -1081,6 +1113,8 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
|
||||||
c = server_request_session();
|
c = server_request_session();
|
||||||
} else if (strcmp(ctype, "direct-tcpip") == 0) {
|
} else if (strcmp(ctype, "direct-tcpip") == 0) {
|
||||||
c = server_request_direct_tcpip();
|
c = server_request_direct_tcpip();
|
||||||
|
} else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) {
|
||||||
|
c = server_request_direct_streamlocal();
|
||||||
} else if (strcmp(ctype, "tun@openssh.com") == 0) {
|
} else if (strcmp(ctype, "tun@openssh.com") == 0) {
|
||||||
c = server_request_tun();
|
c = server_request_tun();
|
||||||
}
|
}
|
||||||
|
@ -1125,47 +1159,74 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
|
||||||
/* -R style forwarding */
|
/* -R style forwarding */
|
||||||
if (strcmp(rtype, "tcpip-forward") == 0) {
|
if (strcmp(rtype, "tcpip-forward") == 0) {
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
char *listen_address;
|
struct Forward fwd;
|
||||||
u_short listen_port;
|
|
||||||
|
|
||||||
pw = the_authctxt->pw;
|
pw = the_authctxt->pw;
|
||||||
if (pw == NULL || !the_authctxt->valid)
|
if (pw == NULL || !the_authctxt->valid)
|
||||||
fatal("server_input_global_request: no/invalid user");
|
fatal("server_input_global_request: no/invalid user");
|
||||||
listen_address = packet_get_string(NULL);
|
memset(&fwd, 0, sizeof(fwd));
|
||||||
listen_port = (u_short)packet_get_int();
|
fwd.listen_host = packet_get_string(NULL);
|
||||||
|
fwd.listen_port = (u_short)packet_get_int();
|
||||||
debug("server_input_global_request: tcpip-forward listen %s port %d",
|
debug("server_input_global_request: tcpip-forward listen %s port %d",
|
||||||
listen_address, listen_port);
|
fwd.listen_host, fwd.listen_port);
|
||||||
|
|
||||||
/* check permissions */
|
/* check permissions */
|
||||||
if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
|
if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
|
||||||
no_port_forwarding_flag ||
|
no_port_forwarding_flag ||
|
||||||
(!want_reply && listen_port == 0)
|
(!want_reply && fwd.listen_port == 0) ||
|
||||||
#ifndef NO_IPPORT_RESERVED_CONCEPT
|
#ifndef NO_IPPORT_RESERVED_CONCEPT
|
||||||
|| (listen_port != 0 && listen_port < IPPORT_RESERVED &&
|
(fwd.listen_port != 0 && fwd.listen_port < IPPORT_RESERVED &&
|
||||||
pw->pw_uid != 0)
|
pw->pw_uid != 0)
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
success = 0;
|
success = 0;
|
||||||
packet_send_debug("Server has disabled port forwarding.");
|
packet_send_debug("Server has disabled port forwarding.");
|
||||||
} else {
|
} else {
|
||||||
/* Start listening on the port */
|
/* Start listening on the port */
|
||||||
success = channel_setup_remote_fwd_listener(
|
success = channel_setup_remote_fwd_listener(&fwd,
|
||||||
listen_address, listen_port,
|
&allocated_listen_port, &options.fwd_opts);
|
||||||
&allocated_listen_port, options.gateway_ports);
|
|
||||||
}
|
}
|
||||||
free(listen_address);
|
free(fwd.listen_host);
|
||||||
} else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
|
} else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
|
||||||
char *cancel_address;
|
struct Forward fwd;
|
||||||
u_short cancel_port;
|
|
||||||
|
|
||||||
cancel_address = packet_get_string(NULL);
|
memset(&fwd, 0, sizeof(fwd));
|
||||||
cancel_port = (u_short)packet_get_int();
|
fwd.listen_host = packet_get_string(NULL);
|
||||||
|
fwd.listen_port = (u_short)packet_get_int();
|
||||||
debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
|
debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
|
||||||
cancel_address, cancel_port);
|
fwd.listen_host, fwd.listen_port);
|
||||||
|
|
||||||
success = channel_cancel_rport_listener(cancel_address,
|
success = channel_cancel_rport_listener(&fwd);
|
||||||
cancel_port);
|
free(fwd.listen_host);
|
||||||
free(cancel_address);
|
} else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) {
|
||||||
|
struct Forward fwd;
|
||||||
|
|
||||||
|
memset(&fwd, 0, sizeof(fwd));
|
||||||
|
fwd.listen_path = packet_get_string(NULL);
|
||||||
|
debug("server_input_global_request: streamlocal-forward listen path %s",
|
||||||
|
fwd.listen_path);
|
||||||
|
|
||||||
|
/* check permissions */
|
||||||
|
if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0
|
||||||
|
|| no_port_forwarding_flag) {
|
||||||
|
success = 0;
|
||||||
|
packet_send_debug("Server has disabled port forwarding.");
|
||||||
|
} else {
|
||||||
|
/* Start listening on the socket */
|
||||||
|
success = channel_setup_remote_fwd_listener(
|
||||||
|
&fwd, NULL, &options.fwd_opts);
|
||||||
|
}
|
||||||
|
free(fwd.listen_path);
|
||||||
|
} else if (strcmp(rtype, "cancel-streamlocal-forward@openssh.com") == 0) {
|
||||||
|
struct Forward fwd;
|
||||||
|
|
||||||
|
memset(&fwd, 0, sizeof(fwd));
|
||||||
|
fwd.listen_path = packet_get_string(NULL);
|
||||||
|
debug("%s: cancel-streamlocal-forward path %s", __func__,
|
||||||
|
fwd.listen_path);
|
||||||
|
|
||||||
|
success = channel_cancel_rport_listener(&fwd);
|
||||||
|
free(fwd.listen_path);
|
||||||
} else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
|
} else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
|
||||||
no_more_sessions = 1;
|
no_more_sessions = 1;
|
||||||
success = 1;
|
success = 1;
|
||||||
|
|
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
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
@ -84,11 +84,11 @@
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "sshlogin.h"
|
#include "sshlogin.h"
|
||||||
#include "serverloop.h"
|
#include "serverloop.h"
|
||||||
#include "canohost.h"
|
#include "canohost.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
#include "kex.h"
|
#include "kex.h"
|
||||||
#include "monitor_wrap.h"
|
#include "monitor_wrap.h"
|
||||||
|
@ -183,7 +183,6 @@ auth_input_request_forwarding(struct passwd * pw)
|
||||||
{
|
{
|
||||||
Channel *nc;
|
Channel *nc;
|
||||||
int sock = -1;
|
int sock = -1;
|
||||||
struct sockaddr_un sunaddr;
|
|
||||||
|
|
||||||
if (auth_sock_name != NULL) {
|
if (auth_sock_name != NULL) {
|
||||||
error("authentication forwarding requested twice.");
|
error("authentication forwarding requested twice.");
|
||||||
|
@ -209,33 +208,15 @@ auth_input_request_forwarding(struct passwd * pw)
|
||||||
xasprintf(&auth_sock_name, "%s/agent.%ld",
|
xasprintf(&auth_sock_name, "%s/agent.%ld",
|
||||||
auth_sock_dir, (long) getpid());
|
auth_sock_dir, (long) getpid());
|
||||||
|
|
||||||
/* Create the socket. */
|
/* Start a Unix listener on auth_sock_name. */
|
||||||
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0);
|
||||||
if (sock < 0) {
|
|
||||||
error("socket: %.100s", strerror(errno));
|
|
||||||
restore_uid();
|
|
||||||
goto authsock_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bind it to the name. */
|
|
||||||
memset(&sunaddr, 0, sizeof(sunaddr));
|
|
||||||
sunaddr.sun_family = AF_UNIX;
|
|
||||||
strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
|
|
||||||
|
|
||||||
if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
|
|
||||||
error("bind: %.100s", strerror(errno));
|
|
||||||
restore_uid();
|
|
||||||
goto authsock_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Restore the privileged uid. */
|
/* Restore the privileged uid. */
|
||||||
restore_uid();
|
restore_uid();
|
||||||
|
|
||||||
/* Start listening on the socket. */
|
/* Check for socket/bind/listen failure. */
|
||||||
if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
|
if (sock < 0)
|
||||||
error("listen: %.100s", strerror(errno));
|
|
||||||
goto authsock_err;
|
goto authsock_err;
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate a channel for the authentication agent socket. */
|
/* Allocate a channel for the authentication agent socket. */
|
||||||
nc = channel_new("auth socket",
|
nc = channel_new("auth socket",
|
||||||
|
@ -274,6 +255,7 @@ do_authenticated(Authctxt *authctxt)
|
||||||
setproctitle("%s", authctxt->pw->pw_name);
|
setproctitle("%s", authctxt->pw->pw_name);
|
||||||
|
|
||||||
/* setup the channel layer */
|
/* setup the channel layer */
|
||||||
|
/* XXX - streamlocal? */
|
||||||
if (no_port_forwarding_flag ||
|
if (no_port_forwarding_flag ||
|
||||||
(options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
|
(options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
|
||||||
channel_disable_adm_local_opens();
|
channel_disable_adm_local_opens();
|
||||||
|
@ -393,7 +375,7 @@ do_authenticated1(Authctxt *authctxt)
|
||||||
}
|
}
|
||||||
debug("Received TCP/IP port forwarding request.");
|
debug("Received TCP/IP port forwarding request.");
|
||||||
if (channel_input_port_forward_request(s->pw->pw_uid == 0,
|
if (channel_input_port_forward_request(s->pw->pw_uid == 0,
|
||||||
options.gateway_ports) < 0) {
|
&options.fwd_opts) < 0) {
|
||||||
debug("Port forwarding failed.");
|
debug("Port forwarding failed.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -1038,11 +1038,9 @@ main(int ac, char **av)
|
||||||
u_int nalloc;
|
u_int nalloc;
|
||||||
char *shell, *format, *pidstr, *agentsocket = NULL;
|
char *shell, *format, *pidstr, *agentsocket = NULL;
|
||||||
fd_set *readsetp = NULL, *writesetp = NULL;
|
fd_set *readsetp = NULL, *writesetp = NULL;
|
||||||
struct sockaddr_un sunaddr;
|
|
||||||
#ifdef HAVE_SETRLIMIT
|
#ifdef HAVE_SETRLIMIT
|
||||||
struct rlimit rlim;
|
struct rlimit rlim;
|
||||||
#endif
|
#endif
|
||||||
int prev_mask;
|
|
||||||
extern int optind;
|
extern int optind;
|
||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
@ -1161,27 +1159,12 @@ main(int ac, char **av)
|
||||||
* Create socket early so it will exist before command gets run from
|
* Create socket early so it will exist before command gets run from
|
||||||
* the parent.
|
* the parent.
|
||||||
*/
|
*/
|
||||||
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0);
|
||||||
if (sock < 0) {
|
if (sock < 0) {
|
||||||
perror("socket");
|
/* XXX - unix_listener() calls error() not perror() */
|
||||||
*socket_name = '\0'; /* Don't unlink any existing file */
|
*socket_name = '\0'; /* Don't unlink any existing file */
|
||||||
cleanup_exit(1);
|
cleanup_exit(1);
|
||||||
}
|
}
|
||||||
memset(&sunaddr, 0, sizeof(sunaddr));
|
|
||||||
sunaddr.sun_family = AF_UNIX;
|
|
||||||
strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
|
|
||||||
prev_mask = umask(0177);
|
|
||||||
if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) {
|
|
||||||
perror("bind");
|
|
||||||
*socket_name = '\0'; /* Don't unlink any existing file */
|
|
||||||
umask(prev_mask);
|
|
||||||
cleanup_exit(1);
|
|
||||||
}
|
|
||||||
umask(prev_mask);
|
|
||||||
if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
|
|
||||||
perror("listen");
|
|
||||||
cleanup_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fork, and have the parent execute the command, if any, or present
|
* Fork, and have the parent execute the command, if any, or present
|
||||||
|
|
62
ssh.c
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -96,9 +96,9 @@
|
||||||
#include "dispatch.h"
|
#include "dispatch.h"
|
||||||
#include "clientloop.h"
|
#include "clientloop.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "readconf.h"
|
#include "readconf.h"
|
||||||
#include "sshconnect.h"
|
#include "sshconnect.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "kex.h"
|
#include "kex.h"
|
||||||
#include "mac.h"
|
#include "mac.h"
|
||||||
#include "sshpty.h"
|
#include "sshpty.h"
|
||||||
|
@ -423,7 +423,7 @@ main(int ac, char **av)
|
||||||
int timeout_ms;
|
int timeout_ms;
|
||||||
extern int optind, optreset;
|
extern int optind, optreset;
|
||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
Forward fwd;
|
struct Forward fwd;
|
||||||
struct addrinfo *addrs = NULL;
|
struct addrinfo *addrs = NULL;
|
||||||
struct ssh_digest_ctx *md;
|
struct ssh_digest_ctx *md;
|
||||||
u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
|
u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
|
||||||
|
@ -545,7 +545,7 @@ main(int ac, char **av)
|
||||||
options.forward_x11_trusted = 1;
|
options.forward_x11_trusted = 1;
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
options.gateway_ports = 1;
|
options.fwd_opts.gateway_ports = 1;
|
||||||
break;
|
break;
|
||||||
case 'O':
|
case 'O':
|
||||||
if (stdio_forward_host != NULL)
|
if (stdio_forward_host != NULL)
|
||||||
|
@ -1305,15 +1305,17 @@ fork_postauth(void)
|
||||||
static void
|
static void
|
||||||
ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
||||||
{
|
{
|
||||||
Forward *rfwd = (Forward *)ctxt;
|
struct Forward *rfwd = (struct Forward *)ctxt;
|
||||||
|
|
||||||
/* XXX verbose() on failure? */
|
/* XXX verbose() on failure? */
|
||||||
debug("remote forward %s for: listen %s%s%d, connect %s:%d",
|
debug("remote forward %s for: listen %s%s%d, connect %s:%d",
|
||||||
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
|
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
|
||||||
rfwd->listen_host == NULL ? "" : rfwd->listen_host,
|
rfwd->listen_path ? rfwd->listen_path :
|
||||||
rfwd->listen_host == NULL ? "" : ":",
|
rfwd->listen_host ? rfwd->listen_host : "",
|
||||||
rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
|
(rfwd->listen_path || rfwd->listen_host) ? ":" : "",
|
||||||
if (rfwd->listen_port == 0) {
|
rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
|
||||||
|
rfwd->connect_host, rfwd->connect_port);
|
||||||
|
if (rfwd->listen_path == NULL && rfwd->listen_port == 0) {
|
||||||
if (type == SSH2_MSG_REQUEST_SUCCESS) {
|
if (type == SSH2_MSG_REQUEST_SUCCESS) {
|
||||||
rfwd->allocated_port = packet_get_int();
|
rfwd->allocated_port = packet_get_int();
|
||||||
logit("Allocated port %u for remote forward to %s:%d",
|
logit("Allocated port %u for remote forward to %s:%d",
|
||||||
|
@ -1327,12 +1329,21 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == SSH2_MSG_REQUEST_FAILURE) {
|
if (type == SSH2_MSG_REQUEST_FAILURE) {
|
||||||
if (options.exit_on_forward_failure)
|
if (options.exit_on_forward_failure) {
|
||||||
fatal("Error: remote port forwarding failed for "
|
if (rfwd->listen_path != NULL)
|
||||||
"listen port %d", rfwd->listen_port);
|
fatal("Error: remote port forwarding failed "
|
||||||
else
|
"for listen path %s", rfwd->listen_path);
|
||||||
logit("Warning: remote port forwarding failed for "
|
else
|
||||||
"listen port %d", rfwd->listen_port);
|
fatal("Error: remote port forwarding failed "
|
||||||
|
"for listen port %d", rfwd->listen_port);
|
||||||
|
} else {
|
||||||
|
if (rfwd->listen_path != NULL)
|
||||||
|
logit("Warning: remote port forwarding failed "
|
||||||
|
"for listen path %s", rfwd->listen_path);
|
||||||
|
else
|
||||||
|
logit("Warning: remote port forwarding failed "
|
||||||
|
"for listen port %d", rfwd->listen_port);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (++remote_forward_confirms_received == options.num_remote_forwards) {
|
if (++remote_forward_confirms_received == options.num_remote_forwards) {
|
||||||
debug("All remote forwarding requests processed");
|
debug("All remote forwarding requests processed");
|
||||||
|
@ -1380,18 +1391,18 @@ ssh_init_forwarding(void)
|
||||||
for (i = 0; i < options.num_local_forwards; i++) {
|
for (i = 0; i < options.num_local_forwards; i++) {
|
||||||
debug("Local connections to %.200s:%d forwarded to remote "
|
debug("Local connections to %.200s:%d forwarded to remote "
|
||||||
"address %.200s:%d",
|
"address %.200s:%d",
|
||||||
|
(options.local_forwards[i].listen_path != NULL) ?
|
||||||
|
options.local_forwards[i].listen_path :
|
||||||
(options.local_forwards[i].listen_host == NULL) ?
|
(options.local_forwards[i].listen_host == NULL) ?
|
||||||
(options.gateway_ports ? "*" : "LOCALHOST") :
|
(options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
|
||||||
options.local_forwards[i].listen_host,
|
options.local_forwards[i].listen_host,
|
||||||
options.local_forwards[i].listen_port,
|
options.local_forwards[i].listen_port,
|
||||||
|
(options.local_forwards[i].connect_path != NULL) ?
|
||||||
|
options.local_forwards[i].connect_path :
|
||||||
options.local_forwards[i].connect_host,
|
options.local_forwards[i].connect_host,
|
||||||
options.local_forwards[i].connect_port);
|
options.local_forwards[i].connect_port);
|
||||||
success += channel_setup_local_fwd_listener(
|
success += channel_setup_local_fwd_listener(
|
||||||
options.local_forwards[i].listen_host,
|
&options.local_forwards[i], &options.fwd_opts);
|
||||||
options.local_forwards[i].listen_port,
|
|
||||||
options.local_forwards[i].connect_host,
|
|
||||||
options.local_forwards[i].connect_port,
|
|
||||||
options.gateway_ports);
|
|
||||||
}
|
}
|
||||||
if (i > 0 && success != i && options.exit_on_forward_failure)
|
if (i > 0 && success != i && options.exit_on_forward_failure)
|
||||||
fatal("Could not request local forwarding.");
|
fatal("Could not request local forwarding.");
|
||||||
|
@ -1402,17 +1413,18 @@ ssh_init_forwarding(void)
|
||||||
for (i = 0; i < options.num_remote_forwards; i++) {
|
for (i = 0; i < options.num_remote_forwards; i++) {
|
||||||
debug("Remote connections from %.200s:%d forwarded to "
|
debug("Remote connections from %.200s:%d forwarded to "
|
||||||
"local address %.200s:%d",
|
"local address %.200s:%d",
|
||||||
|
(options.remote_forwards[i].listen_path != NULL) ?
|
||||||
|
options.remote_forwards[i].listen_path :
|
||||||
(options.remote_forwards[i].listen_host == NULL) ?
|
(options.remote_forwards[i].listen_host == NULL) ?
|
||||||
"LOCALHOST" : options.remote_forwards[i].listen_host,
|
"LOCALHOST" : options.remote_forwards[i].listen_host,
|
||||||
options.remote_forwards[i].listen_port,
|
options.remote_forwards[i].listen_port,
|
||||||
|
(options.remote_forwards[i].connect_path != NULL) ?
|
||||||
|
options.remote_forwards[i].connect_path :
|
||||||
options.remote_forwards[i].connect_host,
|
options.remote_forwards[i].connect_host,
|
||||||
options.remote_forwards[i].connect_port);
|
options.remote_forwards[i].connect_port);
|
||||||
options.remote_forwards[i].handle =
|
options.remote_forwards[i].handle =
|
||||||
channel_request_remote_forwarding(
|
channel_request_remote_forwarding(
|
||||||
options.remote_forwards[i].listen_host,
|
&options.remote_forwards[i]);
|
||||||
options.remote_forwards[i].listen_port,
|
|
||||||
options.remote_forwards[i].connect_host,
|
|
||||||
options.remote_forwards[i].connect_port);
|
|
||||||
if (options.remote_forwards[i].handle < 0) {
|
if (options.remote_forwards[i].handle < 0) {
|
||||||
if (options.exit_on_forward_failure)
|
if (options.exit_on_forward_failure)
|
||||||
fatal("Could not request remote forwarding.");
|
fatal("Could not request remote forwarding.");
|
||||||
|
|
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
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: ssh_config.5,v 1.190 2014/07/07 08:19:12 djm Exp $
|
.\" $OpenBSD: ssh_config.5,v 1.191 2014/07/15 15:54:14 millert Exp $
|
||||||
.Dd $Mdocdate: July 7 2014 $
|
.Dd $Mdocdate: July 15 2014 $
|
||||||
.Dt SSH_CONFIG 5
|
.Dt SSH_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -1303,6 +1303,33 @@ channel to request a response from the server.
|
||||||
The default
|
The default
|
||||||
is 0, indicating that these messages will not be sent to the server.
|
is 0, indicating that these messages will not be sent to the server.
|
||||||
This option applies to protocol version 2 only.
|
This option applies to protocol version 2 only.
|
||||||
|
.It Cm StreamLocalBindMask
|
||||||
|
Sets the octal file creation mode mask
|
||||||
|
.Pq umask
|
||||||
|
used when creating a Unix-domain socket file for local or remote
|
||||||
|
port forwarding.
|
||||||
|
This option is only used for port forwarding to a Unix-domain socket file.
|
||||||
|
.Pp
|
||||||
|
The default value is 0177, which creates a Unix-domain socket file that is
|
||||||
|
readable and writable only by the owner.
|
||||||
|
Note that not all operating systems honor the file mode on Unix-domain
|
||||||
|
socket files.
|
||||||
|
.It Cm StreamLocalBindUnlink
|
||||||
|
Specifies whether to remove an existing Unix-domain socket file for local
|
||||||
|
or remote port forwarding before creating a new one.
|
||||||
|
If the socket file already exists and
|
||||||
|
.Cm StreamLocalBindUnlink
|
||||||
|
is not enabled,
|
||||||
|
.Nm ssh
|
||||||
|
will be unable to forward the port to the Unix-domain socket file.
|
||||||
|
This option is only used for port forwarding to a Unix-domain socket file.
|
||||||
|
.Pp
|
||||||
|
The argument must be
|
||||||
|
.Dq yes
|
||||||
|
or
|
||||||
|
.Dq no .
|
||||||
|
The default is
|
||||||
|
.Dq no .
|
||||||
.It Cm StrictHostKeyChecking
|
.It Cm StrictHostKeyChecking
|
||||||
If this flag is set to
|
If this flag is set to
|
||||||
.Dq yes ,
|
.Dq yes ,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sshconnect.c,v 1.250 2014/07/03 22:23:46 djm Exp $ */
|
/* $OpenBSD: sshconnect.c,v 1.251 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -54,9 +54,9 @@
|
||||||
#include "sshconnect.h"
|
#include "sshconnect.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "readconf.h"
|
#include "readconf.h"
|
||||||
#include "atomicio.h"
|
#include "atomicio.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "dns.h"
|
#include "dns.h"
|
||||||
#include "roaming.h"
|
#include "roaming.h"
|
||||||
#include "monitor_fdpass.h"
|
#include "monitor_fdpass.h"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sshconnect1.c,v 1.75 2014/06/24 01:13:21 djm Exp $ */
|
/* $OpenBSD: sshconnect1.c,v 1.76 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -38,11 +38,11 @@
|
||||||
#include "kex.h"
|
#include "kex.h"
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "readconf.h"
|
#include "readconf.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "sshconnect.h"
|
#include "sshconnect.h"
|
||||||
#include "authfile.h"
|
#include "authfile.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "canohost.h"
|
#include "canohost.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sshconnect2.c,v 1.209 2014/06/24 01:13:21 djm Exp $ */
|
/* $OpenBSD: sshconnect2.c,v 1.210 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2008 Damien Miller. All rights reserved.
|
* Copyright (c) 2008 Damien Miller. All rights reserved.
|
||||||
|
@ -61,8 +61,8 @@
|
||||||
#include "dh.h"
|
#include "dh.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "readconf.h"
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "readconf.h"
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
#include "dispatch.h"
|
#include "dispatch.h"
|
||||||
#include "canohost.h"
|
#include "canohost.h"
|
||||||
|
|
4
sshd.c
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -93,6 +93,7 @@
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
@ -108,7 +109,6 @@
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "misc.h"
|
|
||||||
#include "msg.h"
|
#include "msg.h"
|
||||||
#include "dispatch.h"
|
#include "dispatch.h"
|
||||||
#include "channels.h"
|
#include "channels.h"
|
||||||
|
|
|
@ -33,8 +33,8 @@
|
||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: sshd_config.5,v 1.174 2014/07/03 22:40:43 djm Exp $
|
.\" $OpenBSD: sshd_config.5,v 1.175 2014/07/15 15:54:14 millert Exp $
|
||||||
.Dd $Mdocdate: July 3 2014 $
|
.Dd $Mdocdate: July 15 2014 $
|
||||||
.Dt SSHD_CONFIG 5
|
.Dt SSHD_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -140,6 +140,26 @@ The default is
|
||||||
Note that disabling TCP forwarding does not improve security unless
|
Note that disabling TCP forwarding does not improve security unless
|
||||||
users are also denied shell access, as they can always install their
|
users are also denied shell access, as they can always install their
|
||||||
own forwarders.
|
own forwarders.
|
||||||
|
.It Cm AllowStreamLocalForwarding
|
||||||
|
Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted.
|
||||||
|
The available options are
|
||||||
|
.Dq yes
|
||||||
|
or
|
||||||
|
.Dq all
|
||||||
|
to allow StreamLocal forwarding,
|
||||||
|
.Dq no
|
||||||
|
to prevent all StreamLocal forwarding,
|
||||||
|
.Dq local
|
||||||
|
to allow local (from the perspective of
|
||||||
|
.Xr ssh 1 )
|
||||||
|
forwarding only or
|
||||||
|
.Dq remote
|
||||||
|
to allow remote forwarding only.
|
||||||
|
The default is
|
||||||
|
.Dq yes .
|
||||||
|
Note that disabling StreamLocal forwarding does not improve security unless
|
||||||
|
users are also denied shell access, as they can always install their
|
||||||
|
own forwarders.
|
||||||
.It Cm AllowUsers
|
.It Cm AllowUsers
|
||||||
This keyword can be followed by a list of user name patterns, separated
|
This keyword can be followed by a list of user name patterns, separated
|
||||||
by spaces.
|
by spaces.
|
||||||
|
@ -1171,6 +1191,33 @@ This option applies to protocol version 1 only.
|
||||||
.It Cm ServerKeyBits
|
.It Cm ServerKeyBits
|
||||||
Defines the number of bits in the ephemeral protocol version 1 server key.
|
Defines the number of bits in the ephemeral protocol version 1 server key.
|
||||||
The minimum value is 512, and the default is 1024.
|
The minimum value is 512, and the default is 1024.
|
||||||
|
.It Cm StreamLocalBindMask
|
||||||
|
Sets the octal file creation mode mask
|
||||||
|
.Pq umask
|
||||||
|
used when creating a Unix-domain socket file for local or remote
|
||||||
|
port forwarding.
|
||||||
|
This option is only used for port forwarding to a Unix-domain socket file.
|
||||||
|
.Pp
|
||||||
|
The default value is 0177, which creates a Unix-domain socket file that is
|
||||||
|
readable and writable only by the owner.
|
||||||
|
Note that not all operating systems honor the file mode on Unix-domain
|
||||||
|
socket files.
|
||||||
|
.It Cm StreamLocalBindUnlink
|
||||||
|
Specifies whether to remove an existing Unix-domain socket file for local
|
||||||
|
or remote port forwarding before creating a new one.
|
||||||
|
If the socket file already exists and
|
||||||
|
.Cm StreamLocalBindUnlink
|
||||||
|
is not enabled,
|
||||||
|
.Nm sshd
|
||||||
|
will be unable to forward the port to the Unix-domain socket file.
|
||||||
|
This option is only used for port forwarding to a Unix-domain socket file.
|
||||||
|
.Pp
|
||||||
|
The argument must be
|
||||||
|
.Dq yes
|
||||||
|
or
|
||||||
|
.Dq no .
|
||||||
|
The default is
|
||||||
|
.Dq no .
|
||||||
.It Cm StrictModes
|
.It Cm StrictModes
|
||||||
Specifies whether
|
Specifies whether
|
||||||
.Xr sshd 8
|
.Xr sshd 8
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sshlogin.c,v 1.28 2014/01/31 16:39:19 tedu Exp $ */
|
/* $OpenBSD: sshlogin.c,v 1.29 2014/07/15 15:54:14 millert Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -58,6 +58,7 @@
|
||||||
#include "loginrec.h"
|
#include "loginrec.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "misc.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
|
|
||||||
extern Buffer loginmsg;
|
extern Buffer loginmsg;
|
||||||
|
|
Loading…
Reference in New Issue