summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--PROTOCOL52
-rw-r--r--auth-chall.c1
-rw-r--r--auth-krb5.c1
-rw-r--r--auth-options.c5
-rw-r--r--auth-passwd.c3
-rw-r--r--auth-rh-rsa.c3
-rw-r--r--auth-rhosts.c4
-rw-r--r--auth-rsa.c4
-rw-r--r--auth.c4
-rw-r--r--auth1.c3
-rw-r--r--auth2-chall.c1
-rw-r--r--auth2-hostbased.c3
-rw-r--r--auth2-kbdint.c3
-rw-r--r--auth2-none.c3
-rw-r--r--auth2-passwd.c3
-rw-r--r--auth2-pubkey.c4
-rw-r--r--auth2.c3
-rw-r--r--canohost.c12
-rw-r--r--channels.c600
-rw-r--r--channels.h28
-rw-r--r--clientloop.c78
-rw-r--r--misc.c49
-rw-r--r--misc.h25
-rw-r--r--monitor.c4
-rw-r--r--mux.c203
-rw-r--r--packet.c4
-rw-r--r--platform.c3
-rw-r--r--readconf.c224
-rw-r--r--readconf.h25
-rw-r--r--sandbox-systrace.c2
-rw-r--r--servconf.c55
-rw-r--r--servconf.h5
-rw-r--r--serverloop.c107
-rw-r--r--session.c34
-rw-r--r--ssh-agent.c23
-rw-r--r--ssh.c62
-rw-r--r--ssh_config.531
-rw-r--r--sshconnect.c4
-rw-r--r--sshconnect1.c4
-rw-r--r--sshconnect2.c4
-rw-r--r--sshd.c4
-rw-r--r--sshd_config.551
-rw-r--r--sshlogin.c3
44 files changed, 1312 insertions, 449 deletions
diff --git a/ChangeLog b/ChangeLog
index d133c5b73..f3f83afe1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
120140718
2 - OpenBSD CVS Sync
3 - millert@cvs.openbsd.org 2014/07/15 15:54:14
4 [PROTOCOL auth-options.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c]
5 [auth-rsa.c auth.c auth1.c auth2-hostbased.c auth2-kbdint.c auth2-none.c]
6 [auth2-passwd.c auth2-pubkey.c auth2.c canohost.c channels.c channels.h]
7 [clientloop.c misc.c misc.h monitor.c mux.c packet.c readconf.c]
8 [readconf.h servconf.c servconf.h serverloop.c session.c ssh-agent.c]
9 [ssh.c ssh_config.5 sshconnect.c sshconnect1.c sshconnect2.c sshd.c]
10 [sshd_config.5 sshlogin.c]
11 Add support for Unix domain socket forwarding. A remote TCP port
12 may be forwarded to a local Unix domain socket and vice versa or
13 both ends may be a Unix domain socket. This is a reimplementation
14 of the streamlocal patches by William Ahern from:
15 http://www.25thandclement.com/~william/projects/streamlocal.html
16 OK djm@ markus@
17
120140717 1820140717
2 - (djm) [digest-openssl.c] Preserve array order when disabling digests. 19 - (djm) [digest-openssl.c] Preserve array order when disabling digests.
3 Reported by Petr Lautrbach. 20 Reported by Petr Lautrbach.
diff --git a/PROTOCOL b/PROTOCOL
index 4a5088f90..aa59f584e 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -232,6 +232,56 @@ The contents of the "data" field for layer 2 packets is:
232The "frame" field contains an IEEE 802.3 Ethernet frame, including 232The "frame" field contains an IEEE 802.3 Ethernet frame, including
233header. 233header.
234 234
2352.4. connection: Unix domain socket forwarding
236
237OpenSSH supports local and remote Unix domain socket forwarding
238using the "streamlocal" extension. Forwarding is initiated as per
239TCP sockets but with a single path instead of a host and port.
240
241Similar to direct-tcpip, direct-streamlocal is sent by the client
242to request that the server make a connection to a Unix domain socket.
243
244 byte SSH_MSG_CHANNEL_OPEN
245 string "direct-streamlocal@openssh.com"
246 uint32 sender channel
247 uint32 initial window size
248 uint32 maximum packet size
249 string socket path
250 string reserved for future use
251
252Similar to forwarded-tcpip, forwarded-streamlocal is sent by the
253server when the client has previously send the server a streamlocal-forward
254GLOBAL_REQUEST.
255
256 byte SSH_MSG_CHANNEL_OPEN
257 string "forwarded-streamlocal@openssh.com"
258 uint32 sender channel
259 uint32 initial window size
260 uint32 maximum packet size
261 string socket path
262 string reserved for future use
263
264The reserved field is not currently defined and is ignored on the
265remote end. It is intended to be used in the future to pass
266information about the socket file, such as ownership and mode.
267The client currently sends the empty string for this field.
268
269Similar to tcpip-forward, streamlocal-forward is sent by the client
270to request remote forwarding of a Unix domain socket.
271
272 byte SSH2_MSG_GLOBAL_REQUEST
273 string "streamlocal-forward@openssh.com"
274 boolean TRUE
275 string socket path
276
277Similar to cancel-tcpip-forward, cancel-streamlocal-forward is sent
278by the client cancel the forwarding of a Unix domain socket.
279
280 byte SSH2_MSG_GLOBAL_REQUEST
281 string "cancel-streamlocal-forward@openssh.com"
282 boolean FALSE
283 string socket path
284
2353. SFTP protocol changes 2853. SFTP protocol changes
236 286
2373.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK 2873.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK
@@ -356,4 +406,4 @@ respond with a SSH_FXP_STATUS message.
356This extension is advertised in the SSH_FXP_VERSION hello with version 406This extension is advertised in the SSH_FXP_VERSION hello with version
357"1". 407"1".
358 408
359$OpenBSD: PROTOCOL,v 1.23 2013/12/01 23:19:05 djm Exp $ 409$OpenBSD: PROTOCOL,v 1.24 2014/07/15 15:54:14 millert Exp $
diff --git a/auth-chall.c b/auth-chall.c
index cb3d522d9..5c26a403d 100644
--- a/auth-chall.c
+++ b/auth-chall.c
@@ -37,6 +37,7 @@
37#include "hostfile.h" 37#include "hostfile.h"
38#include "auth.h" 38#include "auth.h"
39#include "log.h" 39#include "log.h"
40#include "misc.h"
40#include "servconf.h" 41#include "servconf.h"
41 42
42/* limited protocol v1 interface to kbd-interactive authentication */ 43/* limited protocol v1 interface to kbd-interactive authentication */
diff --git a/auth-krb5.c b/auth-krb5.c
index 6c62bdf54..0089b1844 100644
--- a/auth-krb5.c
+++ b/auth-krb5.c
@@ -40,6 +40,7 @@
40#include "packet.h" 40#include "packet.h"
41#include "log.h" 41#include "log.h"
42#include "buffer.h" 42#include "buffer.h"
43#include "misc.h"
43#include "servconf.h" 44#include "servconf.h"
44#include "uidswap.h" 45#include "uidswap.h"
45#include "key.h" 46#include "key.h"
diff --git a/auth-options.c b/auth-options.c
index 9a3c270e9..f3d9c9df8 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-options.c,v 1.63 2014/06/24 01:13:21 djm Exp $ */ 1/* $OpenBSD: auth-options.c,v 1.64 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -26,9 +26,9 @@
26#include "log.h" 26#include "log.h"
27#include "canohost.h" 27#include "canohost.h"
28#include "buffer.h" 28#include "buffer.h"
29#include "misc.h"
29#include "channels.h" 30#include "channels.h"
30#include "servconf.h" 31#include "servconf.h"
31#include "misc.h"
32#include "key.h" 32#include "key.h"
33#include "auth-options.h" 33#include "auth-options.h"
34#include "hostfile.h" 34#include "hostfile.h"
@@ -325,6 +325,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
325 patterns[i] = '\0'; 325 patterns[i] = '\0';
326 opts++; 326 opts++;
327 p = patterns; 327 p = patterns;
328 /* XXX - add streamlocal support */
328 host = hpdelim(&p); 329 host = hpdelim(&p);
329 if (host == NULL || strlen(host) >= NI_MAXHOST) { 330 if (host == NULL || strlen(host) >= NI_MAXHOST) {
330 debug("%.100s, line %lu: Bad permitopen " 331 debug("%.100s, line %lu: Bad permitopen "
diff --git a/auth-passwd.c b/auth-passwd.c
index 68bbd18dd..63ccf3cab 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-passwd.c,v 1.43 2007/09/21 08:15:29 djm Exp $ */ 1/* $OpenBSD: auth-passwd.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -48,6 +48,7 @@
48#include "packet.h" 48#include "packet.h"
49#include "buffer.h" 49#include "buffer.h"
50#include "log.h" 50#include "log.h"
51#include "misc.h"
51#include "servconf.h" 52#include "servconf.h"
52#include "key.h" 53#include "key.h"
53#include "hostfile.h" 54#include "hostfile.h"
diff --git a/auth-rh-rsa.c b/auth-rh-rsa.c
index b21a0f4a2..b7fd064e7 100644
--- a/auth-rh-rsa.c
+++ b/auth-rh-rsa.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-rh-rsa.c,v 1.43 2010/03/04 10:36:03 djm Exp $ */ 1/* $OpenBSD: auth-rh-rsa.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -24,6 +24,7 @@
24#include "uidswap.h" 24#include "uidswap.h"
25#include "log.h" 25#include "log.h"
26#include "buffer.h" 26#include "buffer.h"
27#include "misc.h"
27#include "servconf.h" 28#include "servconf.h"
28#include "key.h" 29#include "key.h"
29#include "hostfile.h" 30#include "hostfile.h"
diff --git a/auth-rhosts.c b/auth-rhosts.c
index 06ae7f0b9..b5bedee8d 100644
--- a/auth-rhosts.c
+++ b/auth-rhosts.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-rhosts.c,v 1.44 2010/03/07 11:57:13 dtucker Exp $ */ 1/* $OpenBSD: auth-rhosts.c,v 1.45 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -34,12 +34,12 @@
34#include "uidswap.h" 34#include "uidswap.h"
35#include "pathnames.h" 35#include "pathnames.h"
36#include "log.h" 36#include "log.h"
37#include "misc.h"
37#include "servconf.h" 38#include "servconf.h"
38#include "canohost.h" 39#include "canohost.h"
39#include "key.h" 40#include "key.h"
40#include "hostfile.h" 41#include "hostfile.h"
41#include "auth.h" 42#include "auth.h"
42#include "misc.h"
43 43
44/* import */ 44/* import */
45extern ServerOptions options; 45extern ServerOptions options;
diff --git a/auth-rsa.c b/auth-rsa.c
index 1bddfa02f..e9f4ede26 100644
--- a/auth-rsa.c
+++ b/auth-rsa.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-rsa.c,v 1.87 2014/06/24 01:13:21 djm Exp $ */ 1/* $OpenBSD: auth-rsa.c,v 1.88 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,6 +35,7 @@
35#include "buffer.h" 35#include "buffer.h"
36#include "pathnames.h" 36#include "pathnames.h"
37#include "log.h" 37#include "log.h"
38#include "misc.h"
38#include "servconf.h" 39#include "servconf.h"
39#include "key.h" 40#include "key.h"
40#include "auth-options.h" 41#include "auth-options.h"
@@ -45,7 +46,6 @@
45#endif 46#endif
46#include "monitor_wrap.h" 47#include "monitor_wrap.h"
47#include "ssh.h" 48#include "ssh.h"
48#include "misc.h"
49 49
50#include "digest.h" 50#include "digest.h"
51 51
diff --git a/auth.c b/auth.c
index 890dde046..5e60682ce 100644
--- a/auth.c
+++ b/auth.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.c,v 1.105 2014/07/03 11:16:55 djm Exp $ */ 1/* $OpenBSD: auth.c,v 1.106 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -56,6 +56,7 @@
56#include "groupaccess.h" 56#include "groupaccess.h"
57#include "log.h" 57#include "log.h"
58#include "buffer.h" 58#include "buffer.h"
59#include "misc.h"
59#include "servconf.h" 60#include "servconf.h"
60#include "key.h" 61#include "key.h"
61#include "hostfile.h" 62#include "hostfile.h"
@@ -63,7 +64,6 @@
63#include "auth-options.h" 64#include "auth-options.h"
64#include "canohost.h" 65#include "canohost.h"
65#include "uidswap.h" 66#include "uidswap.h"
66#include "misc.h"
67#include "packet.h" 67#include "packet.h"
68#include "loginrec.h" 68#include "loginrec.h"
69#ifdef GSSAPI 69#ifdef GSSAPI
diff --git a/auth1.c b/auth1.c
index d758a3d69..50388285c 100644
--- a/auth1.c
+++ b/auth1.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth1.c,v 1.81 2014/07/03 11:16:55 djm Exp $ */ 1/* $OpenBSD: auth1.c,v 1.82 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 4 * All rights reserved
@@ -27,6 +27,7 @@
27#include "packet.h" 27#include "packet.h"
28#include "buffer.h" 28#include "buffer.h"
29#include "log.h" 29#include "log.h"
30#include "misc.h"
30#include "servconf.h" 31#include "servconf.h"
31#include "compat.h" 32#include "compat.h"
32#include "key.h" 33#include "key.h"
diff --git a/auth2-chall.c b/auth2-chall.c
index 980250a91..ea4eb6952 100644
--- a/auth2-chall.c
+++ b/auth2-chall.c
@@ -41,6 +41,7 @@
41#include "packet.h" 41#include "packet.h"
42#include "dispatch.h" 42#include "dispatch.h"
43#include "log.h" 43#include "log.h"
44#include "misc.h"
44#include "servconf.h" 45#include "servconf.h"
45 46
46/* import */ 47/* import */
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index 488008f62..6787e4ca4 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-hostbased.c,v 1.17 2013/12/30 23:52:27 djm Exp $ */ 1/* $OpenBSD: auth2-hostbased.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -36,6 +36,7 @@
36#include "packet.h" 36#include "packet.h"
37#include "buffer.h" 37#include "buffer.h"
38#include "log.h" 38#include "log.h"
39#include "misc.h"
39#include "servconf.h" 40#include "servconf.h"
40#include "compat.h" 41#include "compat.h"
41#include "key.h" 42#include "key.h"
diff --git a/auth2-kbdint.c b/auth2-kbdint.c
index c39bdc62d..bf75c6059 100644
--- a/auth2-kbdint.c
+++ b/auth2-kbdint.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-kbdint.c,v 1.6 2013/05/17 00:13:13 djm Exp $ */ 1/* $OpenBSD: auth2-kbdint.c,v 1.7 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -36,6 +36,7 @@
36#include "auth.h" 36#include "auth.h"
37#include "log.h" 37#include "log.h"
38#include "buffer.h" 38#include "buffer.h"
39#include "misc.h"
39#include "servconf.h" 40#include "servconf.h"
40 41
41/* import */ 42/* import */
diff --git a/auth2-none.c b/auth2-none.c
index 5501b9d64..e71e2219c 100644
--- a/auth2-none.c
+++ b/auth2-none.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-none.c,v 1.17 2014/06/24 01:13:21 djm Exp $ */ 1/* $OpenBSD: auth2-none.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -43,6 +43,7 @@
43#include "packet.h" 43#include "packet.h"
44#include "log.h" 44#include "log.h"
45#include "buffer.h" 45#include "buffer.h"
46#include "misc.h"
46#include "servconf.h" 47#include "servconf.h"
47#include "compat.h" 48#include "compat.h"
48#include "ssh2.h" 49#include "ssh2.h"
diff --git a/auth2-passwd.c b/auth2-passwd.c
index 707680cd0..b638e8715 100644
--- a/auth2-passwd.c
+++ b/auth2-passwd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-passwd.c,v 1.11 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: auth2-passwd.c,v 1.12 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -41,6 +41,7 @@
41#include "ssh-gss.h" 41#include "ssh-gss.h"
42#endif 42#endif
43#include "monitor_wrap.h" 43#include "monitor_wrap.h"
44#include "misc.h"
44#include "servconf.h" 45#include "servconf.h"
45 46
46/* import */ 47/* import */
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index b2fd07a61..f3ca96592 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-pubkey.c,v 1.40 2014/06/24 01:13:21 djm Exp $ */ 1/* $OpenBSD: auth2-pubkey.c,v 1.41 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -48,6 +48,7 @@
48#include "packet.h" 48#include "packet.h"
49#include "buffer.h" 49#include "buffer.h"
50#include "log.h" 50#include "log.h"
51#include "misc.h"
51#include "servconf.h" 52#include "servconf.h"
52#include "compat.h" 53#include "compat.h"
53#include "key.h" 54#include "key.h"
@@ -61,7 +62,6 @@
61#include "ssh-gss.h" 62#include "ssh-gss.h"
62#endif 63#endif
63#include "monitor_wrap.h" 64#include "monitor_wrap.h"
64#include "misc.h"
65#include "authfile.h" 65#include "authfile.h"
66#include "match.h" 66#include "match.h"
67 67
diff --git a/auth2.c b/auth2.c
index 6572381cb..d9b440ae3 100644
--- a/auth2.c
+++ b/auth2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2.c,v 1.131 2014/07/03 11:16:55 djm Exp $ */ 1/* $OpenBSD: auth2.c,v 1.132 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -41,6 +41,7 @@
41#include "packet.h" 41#include "packet.h"
42#include "log.h" 42#include "log.h"
43#include "buffer.h" 43#include "buffer.h"
44#include "misc.h"
44#include "servconf.h" 45#include "servconf.h"
45#include "compat.h" 46#include "compat.h"
46#include "key.h" 47#include "key.h"
diff --git a/canohost.c b/canohost.c
index a61a8c94d..a3e3bbff8 100644
--- a/canohost.c
+++ b/canohost.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: canohost.c,v 1.70 2014/01/19 04:17:29 dtucker Exp $ */ 1/* $OpenBSD: canohost.c,v 1.71 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -16,6 +16,7 @@
16 16
17#include <sys/types.h> 17#include <sys/types.h>
18#include <sys/socket.h> 18#include <sys/socket.h>
19#include <sys/un.h>
19 20
20#include <netinet/in.h> 21#include <netinet/in.h>
21#include <arpa/inet.h> 22#include <arpa/inet.h>
@@ -262,6 +263,11 @@ get_socket_address(int sock, int remote, int flags)
262 if (addr.ss_family == AF_INET6) 263 if (addr.ss_family == AF_INET6)
263 addrlen = sizeof(struct sockaddr_in6); 264 addrlen = sizeof(struct sockaddr_in6);
264 265
266 if (addr.ss_family == AF_UNIX) {
267 /* Get the Unix domain socket path. */
268 return xstrdup(((struct sockaddr_un *)&addr)->sun_path);
269 }
270
265 ipv64_normalise_mapped(&addr, &addrlen); 271 ipv64_normalise_mapped(&addr, &addrlen);
266 272
267 /* Get the address in ascii. */ 273 /* Get the address in ascii. */
@@ -384,6 +390,10 @@ get_sock_port(int sock, int local)
384 if (from.ss_family == AF_INET6) 390 if (from.ss_family == AF_INET6)
385 fromlen = sizeof(struct sockaddr_in6); 391 fromlen = sizeof(struct sockaddr_in6);
386 392
393 /* Unix domain sockets don't have a port number. */
394 if (from.ss_family == AF_UNIX)
395 return 0;
396
387 /* Return port number. */ 397 /* Return port number. */
388 if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, 398 if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
389 strport, sizeof(strport), NI_NUMERICSERV)) != 0) 399 strport, sizeof(strport), NI_NUMERICSERV)) != 0)
diff --git a/channels.c b/channels.c
index dcd75346b..d67fdf48b 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.335 2014/07/05 23:11:48 djm Exp $ */ 1/* $OpenBSD: channels.c,v 1.336 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -42,6 +42,7 @@
42#include "includes.h" 42#include "includes.h"
43 43
44#include <sys/types.h> 44#include <sys/types.h>
45#include <sys/stat.h>
45#include <sys/ioctl.h> 46#include <sys/ioctl.h>
46#include <sys/un.h> 47#include <sys/un.h>
47#include <sys/socket.h> 48#include <sys/socket.h>
@@ -107,11 +108,15 @@ static int channel_max_fd = 0;
107 * a corrupt remote server from accessing arbitrary TCP/IP ports on our local 108 * a corrupt remote server from accessing arbitrary TCP/IP ports on our local
108 * network (which might be behind a firewall). 109 * network (which might be behind a firewall).
109 */ 110 */
111/* XXX: streamlocal wants a path instead of host:port */
112/* Overload host_to_connect; we could just make this match Forward */
113/* XXX - can we use listen_host instead of listen_path? */
110typedef struct { 114typedef struct {
111 char *host_to_connect; /* Connect to 'host'. */ 115 char *host_to_connect; /* Connect to 'host'. */
112 u_short port_to_connect; /* Connect to 'port'. */ 116 int port_to_connect; /* Connect to 'port'. */
113 char *listen_host; /* Remote side should listen address. */ 117 char *listen_host; /* Remote side should listen address. */
114 u_short listen_port; /* Remote side should listen port. */ 118 char *listen_path; /* Remote side should listen path. */
119 int listen_port; /* Remote side should listen port. */
115} ForwardPermission; 120} ForwardPermission;
116 121
117/* List of all permitted host/port pairs to connect by the user. */ 122/* List of all permitted host/port pairs to connect by the user. */
@@ -474,6 +479,8 @@ channel_stop_listening(void)
474 case SSH_CHANNEL_PORT_LISTENER: 479 case SSH_CHANNEL_PORT_LISTENER:
475 case SSH_CHANNEL_RPORT_LISTENER: 480 case SSH_CHANNEL_RPORT_LISTENER:
476 case SSH_CHANNEL_X11_LISTENER: 481 case SSH_CHANNEL_X11_LISTENER:
482 case SSH_CHANNEL_UNIX_LISTENER:
483 case SSH_CHANNEL_RUNIX_LISTENER:
477 channel_close_fd(&c->sock); 484 channel_close_fd(&c->sock);
478 channel_free(c); 485 channel_free(c);
479 break; 486 break;
@@ -536,6 +543,8 @@ channel_still_open(void)
536 case SSH_CHANNEL_CONNECTING: 543 case SSH_CHANNEL_CONNECTING:
537 case SSH_CHANNEL_ZOMBIE: 544 case SSH_CHANNEL_ZOMBIE:
538 case SSH_CHANNEL_ABANDONED: 545 case SSH_CHANNEL_ABANDONED:
546 case SSH_CHANNEL_UNIX_LISTENER:
547 case SSH_CHANNEL_RUNIX_LISTENER:
539 continue; 548 continue;
540 case SSH_CHANNEL_LARVAL: 549 case SSH_CHANNEL_LARVAL:
541 if (!compat20) 550 if (!compat20)
@@ -582,6 +591,8 @@ channel_find_open(void)
582 case SSH_CHANNEL_CONNECTING: 591 case SSH_CHANNEL_CONNECTING:
583 case SSH_CHANNEL_ZOMBIE: 592 case SSH_CHANNEL_ZOMBIE:
584 case SSH_CHANNEL_ABANDONED: 593 case SSH_CHANNEL_ABANDONED:
594 case SSH_CHANNEL_UNIX_LISTENER:
595 case SSH_CHANNEL_RUNIX_LISTENER:
585 continue; 596 continue;
586 case SSH_CHANNEL_LARVAL: 597 case SSH_CHANNEL_LARVAL:
587 case SSH_CHANNEL_AUTH_SOCKET: 598 case SSH_CHANNEL_AUTH_SOCKET:
@@ -632,6 +643,8 @@ channel_open_message(void)
632 case SSH_CHANNEL_ABANDONED: 643 case SSH_CHANNEL_ABANDONED:
633 case SSH_CHANNEL_MUX_CLIENT: 644 case SSH_CHANNEL_MUX_CLIENT:
634 case SSH_CHANNEL_MUX_LISTENER: 645 case SSH_CHANNEL_MUX_LISTENER:
646 case SSH_CHANNEL_UNIX_LISTENER:
647 case SSH_CHANNEL_RUNIX_LISTENER:
635 continue; 648 continue;
636 case SSH_CHANNEL_LARVAL: 649 case SSH_CHANNEL_LARVAL:
637 case SSH_CHANNEL_OPENING: 650 case SSH_CHANNEL_OPENING:
@@ -1387,7 +1400,6 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
1387static void 1400static void
1388port_open_helper(Channel *c, char *rtype) 1401port_open_helper(Channel *c, char *rtype)
1389{ 1402{
1390 int direct;
1391 char buf[1024]; 1403 char buf[1024];
1392 char *local_ipaddr = get_local_ipaddr(c->sock); 1404 char *local_ipaddr = get_local_ipaddr(c->sock);
1393 int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1); 1405 int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1);
@@ -1401,8 +1413,6 @@ port_open_helper(Channel *c, char *rtype)
1401 remote_port = 65535; 1413 remote_port = 65535;
1402 } 1414 }
1403 1415
1404 direct = (strcmp(rtype, "direct-tcpip") == 0);
1405
1406 snprintf(buf, sizeof buf, 1416 snprintf(buf, sizeof buf,
1407 "%s: listening port %d for %.100s port %d, " 1417 "%s: listening port %d for %.100s port %d, "
1408 "connect from %.200s port %d to %.100s port %d", 1418 "connect from %.200s port %d to %.100s port %d",
@@ -1418,18 +1428,29 @@ port_open_helper(Channel *c, char *rtype)
1418 packet_put_int(c->self); 1428 packet_put_int(c->self);
1419 packet_put_int(c->local_window_max); 1429 packet_put_int(c->local_window_max);
1420 packet_put_int(c->local_maxpacket); 1430 packet_put_int(c->local_maxpacket);
1421 if (direct) { 1431 if (strcmp(rtype, "direct-tcpip") == 0) {
1422 /* target host, port */ 1432 /* target host, port */
1423 packet_put_cstring(c->path); 1433 packet_put_cstring(c->path);
1424 packet_put_int(c->host_port); 1434 packet_put_int(c->host_port);
1435 } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) {
1436 /* target path */
1437 packet_put_cstring(c->path);
1438 } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
1439 /* listen path */
1440 packet_put_cstring(c->path);
1425 } else { 1441 } else {
1426 /* listen address, port */ 1442 /* listen address, port */
1427 packet_put_cstring(c->path); 1443 packet_put_cstring(c->path);
1428 packet_put_int(local_port); 1444 packet_put_int(local_port);
1429 } 1445 }
1430 /* originator host and port */ 1446 if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
1431 packet_put_cstring(remote_ipaddr); 1447 /* reserved for future owner/mode info */
1432 packet_put_int((u_int)remote_port); 1448 packet_put_cstring("");
1449 } else {
1450 /* originator host and port */
1451 packet_put_cstring(remote_ipaddr);
1452 packet_put_int((u_int)remote_port);
1453 }
1433 packet_send(); 1454 packet_send();
1434 } else { 1455 } else {
1435 packet_start(SSH_MSG_PORT_OPEN); 1456 packet_start(SSH_MSG_PORT_OPEN);
@@ -1479,14 +1500,18 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
1479 if (c->type == SSH_CHANNEL_RPORT_LISTENER) { 1500 if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
1480 nextstate = SSH_CHANNEL_OPENING; 1501 nextstate = SSH_CHANNEL_OPENING;
1481 rtype = "forwarded-tcpip"; 1502 rtype = "forwarded-tcpip";
1503 } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) {
1504 nextstate = SSH_CHANNEL_OPENING;
1505 rtype = "forwarded-streamlocal@openssh.com";
1506 } else if (c->host_port == PORT_STREAMLOCAL) {
1507 nextstate = SSH_CHANNEL_OPENING;
1508 rtype = "direct-streamlocal@openssh.com";
1509 } else if (c->host_port == 0) {
1510 nextstate = SSH_CHANNEL_DYNAMIC;
1511 rtype = "dynamic-tcpip";
1482 } else { 1512 } else {
1483 if (c->host_port == 0) { 1513 nextstate = SSH_CHANNEL_OPENING;
1484 nextstate = SSH_CHANNEL_DYNAMIC; 1514 rtype = "direct-tcpip";
1485 rtype = "dynamic-tcpip";
1486 } else {
1487 nextstate = SSH_CHANNEL_OPENING;
1488 rtype = "direct-tcpip";
1489 }
1490 } 1515 }
1491 1516
1492 addrlen = sizeof(addr); 1517 addrlen = sizeof(addr);
@@ -1499,7 +1524,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
1499 c->notbefore = monotime() + 1; 1524 c->notbefore = monotime() + 1;
1500 return; 1525 return;
1501 } 1526 }
1502 set_nodelay(newsock); 1527 if (c->host_port != PORT_STREAMLOCAL)
1528 set_nodelay(newsock);
1503 nc = channel_new(rtype, nextstate, newsock, newsock, -1, 1529 nc = channel_new(rtype, nextstate, newsock, newsock, -1,
1504 c->local_window_max, c->local_maxpacket, 0, rtype, 1); 1530 c->local_window_max, c->local_maxpacket, 0, rtype, 1);
1505 nc->listening_port = c->listening_port; 1531 nc->listening_port = c->listening_port;
@@ -1988,6 +2014,8 @@ channel_handler_init_20(void)
1988 channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; 2014 channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
1989 channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; 2015 channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
1990 channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; 2016 channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener;
2017 channel_pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener;
2018 channel_pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener;
1991 channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; 2019 channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
1992 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; 2020 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
1993 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; 2021 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
@@ -1998,6 +2026,8 @@ channel_handler_init_20(void)
1998 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; 2026 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
1999 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; 2027 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
2000 channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; 2028 channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener;
2029 channel_post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener;
2030 channel_post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener;
2001 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; 2031 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
2002 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; 2032 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
2003 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; 2033 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
@@ -2638,7 +2668,7 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt)
2638 originator_string = xstrdup("unknown (remote did not supply name)"); 2668 originator_string = xstrdup("unknown (remote did not supply name)");
2639 } 2669 }
2640 packet_check_eom(); 2670 packet_check_eom();
2641 c = channel_connect_to(host, host_port, 2671 c = channel_connect_to_port(host, host_port,
2642 "connected socket", originator_string); 2672 "connected socket", originator_string);
2643 free(originator_string); 2673 free(originator_string);
2644 free(host); 2674 free(host);
@@ -2705,20 +2735,20 @@ channel_set_af(int af)
2705 */ 2735 */
2706static const char * 2736static const char *
2707channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, 2737channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
2708 int is_client, int gateway_ports) 2738 int is_client, struct ForwardOptions *fwd_opts)
2709{ 2739{
2710 const char *addr = NULL; 2740 const char *addr = NULL;
2711 int wildcard = 0; 2741 int wildcard = 0;
2712 2742
2713 if (listen_addr == NULL) { 2743 if (listen_addr == NULL) {
2714 /* No address specified: default to gateway_ports setting */ 2744 /* No address specified: default to gateway_ports setting */
2715 if (gateway_ports) 2745 if (fwd_opts->gateway_ports)
2716 wildcard = 1; 2746 wildcard = 1;
2717 } else if (gateway_ports || is_client) { 2747 } else if (fwd_opts->gateway_ports || is_client) {
2718 if (((datafellows & SSH_OLD_FORWARD_ADDR) && 2748 if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
2719 strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) || 2749 strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
2720 *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || 2750 *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
2721 (!is_client && gateway_ports == 1)) { 2751 (!is_client && fwd_opts->gateway_ports == 1)) {
2722 wildcard = 1; 2752 wildcard = 1;
2723 /* 2753 /*
2724 * Notify client if they requested a specific listen 2754 * Notify client if they requested a specific listen
@@ -2752,9 +2782,8 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
2752} 2782}
2753 2783
2754static int 2784static int
2755channel_setup_fwd_listener(int type, const char *listen_addr, 2785channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
2756 u_short listen_port, int *allocated_listen_port, 2786 int *allocated_listen_port, struct ForwardOptions *fwd_opts)
2757 const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2758{ 2787{
2759 Channel *c; 2788 Channel *c;
2760 int sock, r, success = 0, wildcard = 0, is_client; 2789 int sock, r, success = 0, wildcard = 0, is_client;
@@ -2764,7 +2793,7 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2764 in_port_t *lport_p; 2793 in_port_t *lport_p;
2765 2794
2766 host = (type == SSH_CHANNEL_RPORT_LISTENER) ? 2795 host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
2767 listen_addr : host_to_connect; 2796 fwd->listen_host : fwd->connect_host;
2768 is_client = (type == SSH_CHANNEL_PORT_LISTENER); 2797 is_client = (type == SSH_CHANNEL_PORT_LISTENER);
2769 2798
2770 if (host == NULL) { 2799 if (host == NULL) {
@@ -2777,9 +2806,9 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2777 } 2806 }
2778 2807
2779 /* Determine the bind address, cf. channel_fwd_bind_addr() comment */ 2808 /* Determine the bind address, cf. channel_fwd_bind_addr() comment */
2780 addr = channel_fwd_bind_addr(listen_addr, &wildcard, 2809 addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard,
2781 is_client, gateway_ports); 2810 is_client, fwd_opts);
2782 debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s", 2811 debug3("%s: type %d wildcard %d addr %s", __func__,
2783 type, wildcard, (addr == NULL) ? "NULL" : addr); 2812 type, wildcard, (addr == NULL) ? "NULL" : addr);
2784 2813
2785 /* 2814 /*
@@ -2790,15 +2819,14 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2790 hints.ai_family = IPv4or6; 2819 hints.ai_family = IPv4or6;
2791 hints.ai_flags = wildcard ? AI_PASSIVE : 0; 2820 hints.ai_flags = wildcard ? AI_PASSIVE : 0;
2792 hints.ai_socktype = SOCK_STREAM; 2821 hints.ai_socktype = SOCK_STREAM;
2793 snprintf(strport, sizeof strport, "%d", listen_port); 2822 snprintf(strport, sizeof strport, "%d", fwd->listen_port);
2794 if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { 2823 if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
2795 if (addr == NULL) { 2824 if (addr == NULL) {
2796 /* This really shouldn't happen */ 2825 /* This really shouldn't happen */
2797 packet_disconnect("getaddrinfo: fatal error: %s", 2826 packet_disconnect("getaddrinfo: fatal error: %s",
2798 ssh_gai_strerror(r)); 2827 ssh_gai_strerror(r));
2799 } else { 2828 } else {
2800 error("channel_setup_fwd_listener: " 2829 error("%s: getaddrinfo(%.64s): %s", __func__, addr,
2801 "getaddrinfo(%.64s): %s", addr,
2802 ssh_gai_strerror(r)); 2830 ssh_gai_strerror(r));
2803 } 2831 }
2804 return 0; 2832 return 0;
@@ -2822,13 +2850,13 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2822 * If allocating a port for -R forwards, then use the 2850 * If allocating a port for -R forwards, then use the
2823 * same port for all address families. 2851 * same port for all address families.
2824 */ 2852 */
2825 if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && 2853 if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
2826 allocated_listen_port != NULL && *allocated_listen_port > 0) 2854 allocated_listen_port != NULL && *allocated_listen_port > 0)
2827 *lport_p = htons(*allocated_listen_port); 2855 *lport_p = htons(*allocated_listen_port);
2828 2856
2829 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), 2857 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
2830 strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 2858 strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
2831 error("channel_setup_fwd_listener: getnameinfo failed"); 2859 error("%s: getnameinfo failed", __func__);
2832 continue; 2860 continue;
2833 } 2861 }
2834 /* Create a port to listen for the host. */ 2862 /* Create a port to listen for the host. */
@@ -2865,10 +2893,10 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2865 } 2893 }
2866 2894
2867 /* 2895 /*
2868 * listen_port == 0 requests a dynamically allocated port - 2896 * fwd->listen_port == 0 requests a dynamically allocated port -
2869 * record what we got. 2897 * record what we got.
2870 */ 2898 */
2871 if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && 2899 if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
2872 allocated_listen_port != NULL && 2900 allocated_listen_port != NULL &&
2873 *allocated_listen_port == 0) { 2901 *allocated_listen_port == 0) {
2874 *allocated_listen_port = get_sock_port(sock, 1); 2902 *allocated_listen_port = get_sock_port(sock, 1);
@@ -2881,24 +2909,98 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2881 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 2909 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
2882 0, "port listener", 1); 2910 0, "port listener", 1);
2883 c->path = xstrdup(host); 2911 c->path = xstrdup(host);
2884 c->host_port = port_to_connect; 2912 c->host_port = fwd->connect_port;
2885 c->listening_addr = addr == NULL ? NULL : xstrdup(addr); 2913 c->listening_addr = addr == NULL ? NULL : xstrdup(addr);
2886 if (listen_port == 0 && allocated_listen_port != NULL && 2914 if (fwd->listen_port == 0 && allocated_listen_port != NULL &&
2887 !(datafellows & SSH_BUG_DYNAMIC_RPORT)) 2915 !(datafellows & SSH_BUG_DYNAMIC_RPORT))
2888 c->listening_port = *allocated_listen_port; 2916 c->listening_port = *allocated_listen_port;
2889 else 2917 else
2890 c->listening_port = listen_port; 2918 c->listening_port = fwd->listen_port;
2891 success = 1; 2919 success = 1;
2892 } 2920 }
2893 if (success == 0) 2921 if (success == 0)
2894 error("channel_setup_fwd_listener: cannot listen to port: %d", 2922 error("%s: cannot listen to port: %d", __func__,
2895 listen_port); 2923 fwd->listen_port);
2896 freeaddrinfo(aitop); 2924 freeaddrinfo(aitop);
2897 return success; 2925 return success;
2898} 2926}
2899 2927
2900int 2928static int
2901channel_cancel_rport_listener(const char *host, u_short port) 2929channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd,
2930 struct ForwardOptions *fwd_opts)
2931{
2932 struct sockaddr_un sunaddr;
2933 const char *path;
2934 Channel *c;
2935 int port, sock;
2936 mode_t omask;
2937
2938 switch (type) {
2939 case SSH_CHANNEL_UNIX_LISTENER:
2940 if (fwd->connect_path != NULL) {
2941 if (strlen(fwd->connect_path) > sizeof(sunaddr.sun_path)) {
2942 error("Local connecting path too long: %s",
2943 fwd->connect_path);
2944 return 0;
2945 }
2946 path = fwd->connect_path;
2947 port = PORT_STREAMLOCAL;
2948 } else {
2949 if (fwd->connect_host == NULL) {
2950 error("No forward host name.");
2951 return 0;
2952 }
2953 if (strlen(fwd->connect_host) >= NI_MAXHOST) {
2954 error("Forward host name too long.");
2955 return 0;
2956 }
2957 path = fwd->connect_host;
2958 port = fwd->connect_port;
2959 }
2960 break;
2961 case SSH_CHANNEL_RUNIX_LISTENER:
2962 path = fwd->listen_path;
2963 port = PORT_STREAMLOCAL;
2964 break;
2965 default:
2966 error("%s: unexpected channel type %d", __func__, type);
2967 return 0;
2968 }
2969
2970 if (fwd->listen_path == NULL) {
2971 error("No forward path name.");
2972 return 0;
2973 }
2974 if (strlen(fwd->listen_path) > sizeof(sunaddr.sun_path)) {
2975 error("Local listening path too long: %s", fwd->listen_path);
2976 return 0;
2977 }
2978
2979 debug3("%s: type %d path %s", __func__, type, fwd->listen_path);
2980
2981 /* Start a Unix domain listener. */
2982 omask = umask(fwd_opts->streamlocal_bind_mask);
2983 sock = unix_listener(fwd->listen_path, SSH_LISTEN_BACKLOG,
2984 fwd_opts->streamlocal_bind_unlink);
2985 umask(omask);
2986 if (sock < 0)
2987 return 0;
2988
2989 debug("Local forwarding listening on path %s.", fwd->listen_path);
2990
2991 /* Allocate a channel number for the socket. */
2992 c = channel_new("unix listener", type, sock, sock, -1,
2993 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
2994 0, "unix listener", 1);
2995 c->path = xstrdup(path);
2996 c->host_port = port;
2997 c->listening_port = PORT_STREAMLOCAL;
2998 c->listening_addr = xstrdup(fwd->listen_path);
2999 return 1;
3000}
3001
3002static int
3003channel_cancel_rport_listener_tcpip(const char *host, u_short port)
2902{ 3004{
2903 u_int i; 3005 u_int i;
2904 int found = 0; 3006 int found = 0;
@@ -2917,13 +3019,44 @@ channel_cancel_rport_listener(const char *host, u_short port)
2917 return (found); 3019 return (found);
2918} 3020}
2919 3021
3022static int
3023channel_cancel_rport_listener_streamlocal(const char *path)
3024{
3025 u_int i;
3026 int found = 0;
3027
3028 for (i = 0; i < channels_alloc; i++) {
3029 Channel *c = channels[i];
3030 if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER)
3031 continue;
3032 if (c->path == NULL)
3033 continue;
3034 if (strcmp(c->path, path) == 0) {
3035 debug2("%s: close channel %d", __func__, i);
3036 channel_free(c);
3037 found = 1;
3038 }
3039 }
3040
3041 return (found);
3042}
3043
2920int 3044int
2921channel_cancel_lport_listener(const char *lhost, u_short lport, 3045channel_cancel_rport_listener(struct Forward *fwd)
2922 int cport, int gateway_ports) 3046{
3047 if (fwd->listen_path != NULL)
3048 return channel_cancel_rport_listener_streamlocal(fwd->listen_path);
3049 else
3050 return channel_cancel_rport_listener_tcpip(fwd->listen_host, fwd->listen_port);
3051}
3052
3053static int
3054channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport,
3055 int cport, struct ForwardOptions *fwd_opts)
2923{ 3056{
2924 u_int i; 3057 u_int i;
2925 int found = 0; 3058 int found = 0;
2926 const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, gateway_ports); 3059 const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts);
2927 3060
2928 for (i = 0; i < channels_alloc; i++) { 3061 for (i = 0; i < channels_alloc; i++) {
2929 Channel *c = channels[i]; 3062 Channel *c = channels[i];
@@ -2952,24 +3085,68 @@ channel_cancel_lport_listener(const char *lhost, u_short lport,
2952 return (found); 3085 return (found);
2953} 3086}
2954 3087
3088static int
3089channel_cancel_lport_listener_streamlocal(const char *path)
3090{
3091 u_int i;
3092 int found = 0;
3093
3094 if (path == NULL) {
3095 error("%s: no path specified.", __func__);
3096 return 0;
3097 }
3098
3099 for (i = 0; i < channels_alloc; i++) {
3100 Channel *c = channels[i];
3101 if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER)
3102 continue;
3103 if (c->listening_addr == NULL)
3104 continue;
3105 if (strcmp(c->listening_addr, path) == 0) {
3106 debug2("%s: close channel %d", __func__, i);
3107 channel_free(c);
3108 found = 1;
3109 }
3110 }
3111
3112 return (found);
3113}
3114
3115int
3116channel_cancel_lport_listener(struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts)
3117{
3118 if (fwd->listen_path != NULL)
3119 return channel_cancel_lport_listener_streamlocal(fwd->listen_path);
3120 else
3121 return channel_cancel_lport_listener_tcpip(fwd->listen_host, fwd->listen_port, cport, fwd_opts);
3122}
3123
2955/* protocol local port fwd, used by ssh (and sshd in v1) */ 3124/* protocol local port fwd, used by ssh (and sshd in v1) */
2956int 3125int
2957channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port, 3126channel_setup_local_fwd_listener(struct Forward *fwd, struct ForwardOptions *fwd_opts)
2958 const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2959{ 3127{
2960 return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, 3128 if (fwd->listen_path != NULL) {
2961 listen_host, listen_port, NULL, host_to_connect, port_to_connect, 3129 return channel_setup_fwd_listener_streamlocal(
2962 gateway_ports); 3130 SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts);
3131 } else {
3132 return channel_setup_fwd_listener_tcpip(SSH_CHANNEL_PORT_LISTENER,
3133 fwd, NULL, fwd_opts);
3134 }
2963} 3135}
2964 3136
2965/* protocol v2 remote port fwd, used by sshd */ 3137/* protocol v2 remote port fwd, used by sshd */
2966int 3138int
2967channel_setup_remote_fwd_listener(const char *listen_address, 3139channel_setup_remote_fwd_listener(struct Forward *fwd,
2968 u_short listen_port, int *allocated_listen_port, int gateway_ports) 3140 int *allocated_listen_port, struct ForwardOptions *fwd_opts)
2969{ 3141{
2970 return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, 3142 if (fwd->listen_path != NULL) {
2971 listen_address, listen_port, allocated_listen_port, 3143 return channel_setup_fwd_listener_streamlocal(
2972 NULL, 0, gateway_ports); 3144 SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts);
3145 } else {
3146 return channel_setup_fwd_listener_tcpip(
3147 SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port,
3148 fwd_opts);
3149 }
2973} 3150}
2974 3151
2975/* 3152/*
@@ -3000,27 +3177,32 @@ channel_rfwd_bind_host(const char *listen_host)
3000 * channel_update_permitted_opens(). 3177 * channel_update_permitted_opens().
3001 */ 3178 */
3002int 3179int
3003channel_request_remote_forwarding(const char *listen_host, u_short listen_port, 3180channel_request_remote_forwarding(struct Forward *fwd)
3004 const char *host_to_connect, u_short port_to_connect)
3005{ 3181{
3006 int type, success = 0, idx = -1; 3182 int type, success = 0, idx = -1;
3007 3183
3008 /* Send the forward request to the remote side. */ 3184 /* Send the forward request to the remote side. */
3009 if (compat20) { 3185 if (compat20) {
3010 packet_start(SSH2_MSG_GLOBAL_REQUEST); 3186 packet_start(SSH2_MSG_GLOBAL_REQUEST);
3011 packet_put_cstring("tcpip-forward"); 3187 if (fwd->listen_path != NULL) {
3012 packet_put_char(1); /* boolean: want reply */ 3188 packet_put_cstring("streamlocal-forward@openssh.com");
3013 packet_put_cstring(channel_rfwd_bind_host(listen_host)); 3189 packet_put_char(1); /* boolean: want reply */
3014 packet_put_int(listen_port); 3190 packet_put_cstring(fwd->listen_path);
3191 } else {
3192 packet_put_cstring("tcpip-forward");
3193 packet_put_char(1); /* boolean: want reply */
3194 packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host));
3195 packet_put_int(fwd->listen_port);
3196 }
3015 packet_send(); 3197 packet_send();
3016 packet_write_wait(); 3198 packet_write_wait();
3017 /* Assume that server accepts the request */ 3199 /* Assume that server accepts the request */
3018 success = 1; 3200 success = 1;
3019 } else { 3201 } else if (fwd->listen_path == NULL) {
3020 packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); 3202 packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
3021 packet_put_int(listen_port); 3203 packet_put_int(fwd->listen_port);
3022 packet_put_cstring(host_to_connect); 3204 packet_put_cstring(fwd->connect_host);
3023 packet_put_int(port_to_connect); 3205 packet_put_int(fwd->connect_port);
3024 packet_send(); 3206 packet_send();
3025 packet_write_wait(); 3207 packet_write_wait();
3026 3208
@@ -3037,24 +3219,43 @@ channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
3037 packet_disconnect("Protocol error for port forward request:" 3219 packet_disconnect("Protocol error for port forward request:"
3038 "received packet type %d.", type); 3220 "received packet type %d.", type);
3039 } 3221 }
3222 } else {
3223 logit("Warning: Server does not support remote stream local forwarding.");
3040 } 3224 }
3041 if (success) { 3225 if (success) {
3042 /* Record that connection to this host/port is permitted. */ 3226 /* Record that connection to this host/port is permitted. */
3043 permitted_opens = xrealloc(permitted_opens, 3227 permitted_opens = xrealloc(permitted_opens,
3044 num_permitted_opens + 1, sizeof(*permitted_opens)); 3228 num_permitted_opens + 1, sizeof(*permitted_opens));
3045 idx = num_permitted_opens++; 3229 idx = num_permitted_opens++;
3046 permitted_opens[idx].host_to_connect = xstrdup(host_to_connect); 3230 if (fwd->connect_path != NULL) {
3047 permitted_opens[idx].port_to_connect = port_to_connect; 3231 permitted_opens[idx].host_to_connect =
3048 permitted_opens[idx].listen_host = listen_host ? 3232 xstrdup(fwd->connect_path);
3049 xstrdup(listen_host) : NULL; 3233 permitted_opens[idx].port_to_connect =
3050 permitted_opens[idx].listen_port = listen_port; 3234 PORT_STREAMLOCAL;
3235 } else {
3236 permitted_opens[idx].host_to_connect =
3237 xstrdup(fwd->connect_host);
3238 permitted_opens[idx].port_to_connect =
3239 fwd->connect_port;
3240 }
3241 if (fwd->listen_path != NULL) {
3242 permitted_opens[idx].listen_host = NULL;
3243 permitted_opens[idx].listen_path =
3244 xstrdup(fwd->listen_path);
3245 permitted_opens[idx].listen_port = PORT_STREAMLOCAL;
3246 } else {
3247 permitted_opens[idx].listen_host =
3248 fwd->listen_host ? xstrdup(fwd->listen_host) : NULL;
3249 permitted_opens[idx].listen_path = NULL;
3250 permitted_opens[idx].listen_port = fwd->listen_port;
3251 }
3051 } 3252 }
3052 return (idx); 3253 return (idx);
3053} 3254}
3054 3255
3055static int 3256static int
3056open_match(ForwardPermission *allowed_open, const char *requestedhost, 3257open_match(ForwardPermission *allowed_open, const char *requestedhost,
3057 u_short requestedport) 3258 int requestedport)
3058{ 3259{
3059 if (allowed_open->host_to_connect == NULL) 3260 if (allowed_open->host_to_connect == NULL)
3060 return 0; 3261 return 0;
@@ -3067,14 +3268,14 @@ open_match(ForwardPermission *allowed_open, const char *requestedhost,
3067} 3268}
3068 3269
3069/* 3270/*
3070 * Note that in he listen host/port case 3271 * Note that in the listen host/port case
3071 * we don't support FWD_PERMIT_ANY_PORT and 3272 * we don't support FWD_PERMIT_ANY_PORT and
3072 * need to translate between the configured-host (listen_host) 3273 * need to translate between the configured-host (listen_host)
3073 * and what we've sent to the remote server (channel_rfwd_bind_host) 3274 * and what we've sent to the remote server (channel_rfwd_bind_host)
3074 */ 3275 */
3075static int 3276static int
3076open_listen_match(ForwardPermission *allowed_open, const char *requestedhost, 3277open_listen_match_tcpip(ForwardPermission *allowed_open,
3077 u_short requestedport, int translate) 3278 const char *requestedhost, u_short requestedport, int translate)
3078{ 3279{
3079 const char *allowed_host; 3280 const char *allowed_host;
3080 3281
@@ -3094,12 +3295,26 @@ open_listen_match(ForwardPermission *allowed_open, const char *requestedhost,
3094 return 1; 3295 return 1;
3095} 3296}
3096 3297
3298static int
3299open_listen_match_streamlocal(ForwardPermission *allowed_open,
3300 const char *requestedpath)
3301{
3302 if (allowed_open->host_to_connect == NULL)
3303 return 0;
3304 if (allowed_open->listen_port != PORT_STREAMLOCAL)
3305 return 0;
3306 if (allowed_open->listen_path == NULL ||
3307 strcmp(allowed_open->listen_path, requestedpath) != 0)
3308 return 0;
3309 return 1;
3310}
3311
3097/* 3312/*
3098 * Request cancellation of remote forwarding of connection host:port from 3313 * Request cancellation of remote forwarding of connection host:port from
3099 * local side. 3314 * local side.
3100 */ 3315 */
3101int 3316static int
3102channel_request_rforward_cancel(const char *host, u_short port) 3317channel_request_rforward_cancel_tcpip(const char *host, u_short port)
3103{ 3318{
3104 int i; 3319 int i;
3105 3320
@@ -3107,7 +3322,7 @@ channel_request_rforward_cancel(const char *host, u_short port)
3107 return -1; 3322 return -1;
3108 3323
3109 for (i = 0; i < num_permitted_opens; i++) { 3324 for (i = 0; i < num_permitted_opens; i++) {
3110 if (open_listen_match(&permitted_opens[i], host, port, 0)) 3325 if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0))
3111 break; 3326 break;
3112 } 3327 }
3113 if (i >= num_permitted_opens) { 3328 if (i >= num_permitted_opens) {
@@ -3121,15 +3336,68 @@ channel_request_rforward_cancel(const char *host, u_short port)
3121 packet_put_int(port); 3336 packet_put_int(port);
3122 packet_send(); 3337 packet_send();
3123 3338
3124 permitted_opens[i].port_to_connect = 0;
3125 permitted_opens[i].listen_port = 0; 3339 permitted_opens[i].listen_port = 0;
3340 permitted_opens[i].port_to_connect = 0;
3126 free(permitted_opens[i].host_to_connect); 3341 free(permitted_opens[i].host_to_connect);
3127 permitted_opens[i].host_to_connect = NULL; 3342 permitted_opens[i].host_to_connect = NULL;
3128 free(permitted_opens[i].listen_host); 3343 free(permitted_opens[i].listen_host);
3129 permitted_opens[i].listen_host = NULL; 3344 permitted_opens[i].listen_host = NULL;
3345 permitted_opens[i].listen_path = NULL;
3346
3347 return 0;
3348}
3349
3350/*
3351 * Request cancellation of remote forwarding of Unix domain socket
3352 * path from local side.
3353 */
3354static int
3355channel_request_rforward_cancel_streamlocal(const char *path)
3356{
3357 int i;
3358
3359 if (!compat20)
3360 return -1;
3361
3362 for (i = 0; i < num_permitted_opens; i++) {
3363 if (open_listen_match_streamlocal(&permitted_opens[i], path))
3364 break;
3365 }
3366 if (i >= num_permitted_opens) {
3367 debug("%s: requested forward not found", __func__);
3368 return -1;
3369 }
3370 packet_start(SSH2_MSG_GLOBAL_REQUEST);
3371 packet_put_cstring("cancel-streamlocal-forward@openssh.com");
3372 packet_put_char(0);
3373 packet_put_cstring(path);
3374 packet_send();
3375
3376 permitted_opens[i].listen_port = 0;
3377 permitted_opens[i].port_to_connect = 0;
3378 free(permitted_opens[i].host_to_connect);
3379 permitted_opens[i].host_to_connect = NULL;
3380 permitted_opens[i].listen_host = NULL;
3381 free(permitted_opens[i].listen_path);
3382 permitted_opens[i].listen_path = NULL;
3130 3383
3131 return 0; 3384 return 0;
3132} 3385}
3386
3387/*
3388 * Request cancellation of remote forwarding of a connection from local side.
3389 */
3390int
3391channel_request_rforward_cancel(struct Forward *fwd)
3392{
3393 if (fwd->listen_path != NULL) {
3394 return (channel_request_rforward_cancel_streamlocal(
3395 fwd->listen_path));
3396 } else {
3397 return (channel_request_rforward_cancel_tcpip(fwd->listen_host,
3398 fwd->listen_port ? fwd->listen_port : fwd->allocated_port));
3399 }
3400}
3133 3401
3134/* 3402/*
3135 * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates 3403 * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
@@ -3137,36 +3405,35 @@ channel_request_rforward_cancel(const char *host, u_short port)
3137 * message if there was an error). 3405 * message if there was an error).
3138 */ 3406 */
3139int 3407int
3140channel_input_port_forward_request(int is_root, int gateway_ports) 3408channel_input_port_forward_request(int is_root, struct ForwardOptions *fwd_opts)
3141{ 3409{
3142 u_short port, host_port;
3143 int success = 0; 3410 int success = 0;
3144 char *hostname; 3411 struct Forward fwd;
3145 3412
3146 /* Get arguments from the packet. */ 3413 /* Get arguments from the packet. */
3147 port = packet_get_int(); 3414 memset(&fwd, 0, sizeof(fwd));
3148 hostname = packet_get_string(NULL); 3415 fwd.listen_port = packet_get_int();
3149 host_port = packet_get_int(); 3416 fwd.connect_host = packet_get_string(NULL);
3417 fwd.connect_port = packet_get_int();
3150 3418
3151#ifndef HAVE_CYGWIN 3419#ifndef HAVE_CYGWIN
3152 /* 3420 /*
3153 * Check that an unprivileged user is not trying to forward a 3421 * Check that an unprivileged user is not trying to forward a
3154 * privileged port. 3422 * privileged port.
3155 */ 3423 */
3156 if (port < IPPORT_RESERVED && !is_root) 3424 if (fwd.listen_port < IPPORT_RESERVED && !is_root)
3157 packet_disconnect( 3425 packet_disconnect(
3158 "Requested forwarding of port %d but user is not root.", 3426 "Requested forwarding of port %d but user is not root.",
3159 port); 3427 fwd.listen_port);
3160 if (host_port == 0) 3428 if (fwd.connect_port == 0)
3161 packet_disconnect("Dynamic forwarding denied."); 3429 packet_disconnect("Dynamic forwarding denied.");
3162#endif 3430#endif
3163 3431
3164 /* Initiate forwarding */ 3432 /* Initiate forwarding */
3165 success = channel_setup_local_fwd_listener(NULL, port, hostname, 3433 success = channel_setup_local_fwd_listener(&fwd, fwd_opts);
3166 host_port, gateway_ports);
3167 3434
3168 /* Free the argument string. */ 3435 /* Free the argument string. */
3169 free(hostname); 3436 free(fwd.connect_host);
3170 3437
3171 return (success ? 0 : -1); 3438 return (success ? 0 : -1);
3172} 3439}
@@ -3193,6 +3460,7 @@ channel_add_permitted_opens(char *host, int port)
3193 permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); 3460 permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);
3194 permitted_opens[num_permitted_opens].port_to_connect = port; 3461 permitted_opens[num_permitted_opens].port_to_connect = port;
3195 permitted_opens[num_permitted_opens].listen_host = NULL; 3462 permitted_opens[num_permitted_opens].listen_host = NULL;
3463 permitted_opens[num_permitted_opens].listen_path = NULL;
3196 permitted_opens[num_permitted_opens].listen_port = 0; 3464 permitted_opens[num_permitted_opens].listen_port = 0;
3197 num_permitted_opens++; 3465 num_permitted_opens++;
3198 3466
@@ -3227,6 +3495,8 @@ channel_update_permitted_opens(int idx, int newport)
3227 permitted_opens[idx].host_to_connect = NULL; 3495 permitted_opens[idx].host_to_connect = NULL;
3228 free(permitted_opens[idx].listen_host); 3496 free(permitted_opens[idx].listen_host);
3229 permitted_opens[idx].listen_host = NULL; 3497 permitted_opens[idx].listen_host = NULL;
3498 free(permitted_opens[idx].listen_path);
3499 permitted_opens[idx].listen_path = NULL;
3230 } 3500 }
3231} 3501}
3232 3502
@@ -3241,6 +3511,7 @@ channel_add_adm_permitted_opens(char *host, int port)
3241 = xstrdup(host); 3511 = xstrdup(host);
3242 permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port; 3512 permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port;
3243 permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL; 3513 permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL;
3514 permitted_adm_opens[num_adm_permitted_opens].listen_path = NULL;
3244 permitted_adm_opens[num_adm_permitted_opens].listen_port = 0; 3515 permitted_adm_opens[num_adm_permitted_opens].listen_port = 0;
3245 return ++num_adm_permitted_opens; 3516 return ++num_adm_permitted_opens;
3246} 3517}
@@ -3262,6 +3533,7 @@ channel_clear_permitted_opens(void)
3262 for (i = 0; i < num_permitted_opens; i++) { 3533 for (i = 0; i < num_permitted_opens; i++) {
3263 free(permitted_opens[i].host_to_connect); 3534 free(permitted_opens[i].host_to_connect);
3264 free(permitted_opens[i].listen_host); 3535 free(permitted_opens[i].listen_host);
3536 free(permitted_opens[i].listen_path);
3265 } 3537 }
3266 free(permitted_opens); 3538 free(permitted_opens);
3267 permitted_opens = NULL; 3539 permitted_opens = NULL;
@@ -3276,6 +3548,7 @@ channel_clear_adm_permitted_opens(void)
3276 for (i = 0; i < num_adm_permitted_opens; i++) { 3548 for (i = 0; i < num_adm_permitted_opens; i++) {
3277 free(permitted_adm_opens[i].host_to_connect); 3549 free(permitted_adm_opens[i].host_to_connect);
3278 free(permitted_adm_opens[i].listen_host); 3550 free(permitted_adm_opens[i].listen_host);
3551 free(permitted_adm_opens[i].listen_path);
3279 } 3552 }
3280 free(permitted_adm_opens); 3553 free(permitted_adm_opens);
3281 permitted_adm_opens = NULL; 3554 permitted_adm_opens = NULL;
@@ -3319,16 +3592,27 @@ static int
3319connect_next(struct channel_connect *cctx) 3592connect_next(struct channel_connect *cctx)
3320{ 3593{
3321 int sock, saved_errno; 3594 int sock, saved_errno;
3322 char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 3595 struct sockaddr_un *sunaddr;
3596 char ntop[NI_MAXHOST], strport[MAX(NI_MAXSERV,sizeof(sunaddr->sun_path))];
3323 3597
3324 for (; cctx->ai; cctx->ai = cctx->ai->ai_next) { 3598 for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
3325 if (cctx->ai->ai_family != AF_INET && 3599 switch (cctx->ai->ai_family) {
3326 cctx->ai->ai_family != AF_INET6) 3600 case AF_UNIX:
3327 continue; 3601 /* unix:pathname instead of host:port */
3328 if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen, 3602 sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr;
3329 ntop, sizeof(ntop), strport, sizeof(strport), 3603 strlcpy(ntop, "unix", sizeof(ntop));
3330 NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 3604 strlcpy(strport, sunaddr->sun_path, sizeof(strport));
3331 error("connect_next: getnameinfo failed"); 3605 break;
3606 case AF_INET:
3607 case AF_INET6:
3608 if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
3609 ntop, sizeof(ntop), strport, sizeof(strport),
3610 NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
3611 error("connect_next: getnameinfo failed");
3612 continue;
3613 }
3614 break;
3615 default:
3332 continue; 3616 continue;
3333 } 3617 }
3334 if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype, 3618 if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
@@ -3351,10 +3635,11 @@ connect_next(struct channel_connect *cctx)
3351 errno = saved_errno; 3635 errno = saved_errno;
3352 continue; /* fail -- try next */ 3636 continue; /* fail -- try next */
3353 } 3637 }
3638 if (cctx->ai->ai_family != AF_UNIX)
3639 set_nodelay(sock);
3354 debug("connect_next: host %.100s ([%.100s]:%s) " 3640 debug("connect_next: host %.100s ([%.100s]:%s) "
3355 "in progress, fd=%d", cctx->host, ntop, strport, sock); 3641 "in progress, fd=%d", cctx->host, ntop, strport, sock);
3356 cctx->ai = cctx->ai->ai_next; 3642 cctx->ai = cctx->ai->ai_next;
3357 set_nodelay(sock);
3358 return sock; 3643 return sock;
3359 } 3644 }
3360 return -1; 3645 return -1;
@@ -3364,14 +3649,18 @@ static void
3364channel_connect_ctx_free(struct channel_connect *cctx) 3649channel_connect_ctx_free(struct channel_connect *cctx)
3365{ 3650{
3366 free(cctx->host); 3651 free(cctx->host);
3367 if (cctx->aitop) 3652 if (cctx->aitop) {
3368 freeaddrinfo(cctx->aitop); 3653 if (cctx->aitop->ai_family == AF_UNIX)
3654 free(cctx->aitop);
3655 else
3656 freeaddrinfo(cctx->aitop);
3657 }
3369 memset(cctx, 0, sizeof(*cctx)); 3658 memset(cctx, 0, sizeof(*cctx));
3370} 3659}
3371 3660
3372/* Return CONNECTING channel to remote host, port */ 3661/* Return CONNECTING channel to remote host:port or local socket path */
3373static Channel * 3662static Channel *
3374connect_to(const char *host, u_short port, char *ctype, char *rname) 3663connect_to(const char *name, int port, char *ctype, char *rname)
3375{ 3664{
3376 struct addrinfo hints; 3665 struct addrinfo hints;
3377 int gaierr; 3666 int gaierr;
@@ -3381,23 +3670,51 @@ connect_to(const char *host, u_short port, char *ctype, char *rname)
3381 Channel *c; 3670 Channel *c;
3382 3671
3383 memset(&cctx, 0, sizeof(cctx)); 3672 memset(&cctx, 0, sizeof(cctx));
3384 memset(&hints, 0, sizeof(hints)); 3673
3385 hints.ai_family = IPv4or6; 3674 if (port == PORT_STREAMLOCAL) {
3386 hints.ai_socktype = SOCK_STREAM; 3675 struct sockaddr_un *sunaddr;
3387 snprintf(strport, sizeof strport, "%d", port); 3676 struct addrinfo *ai;
3388 if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) { 3677
3389 error("connect_to %.100s: unknown host (%s)", host, 3678 if (strlen(name) > sizeof(sunaddr->sun_path)) {
3390 ssh_gai_strerror(gaierr)); 3679 error("%.100s: %.100s", name, strerror(ENAMETOOLONG));
3391 return NULL; 3680 return (NULL);
3681 }
3682
3683 /*
3684 * Fake up a struct addrinfo for AF_UNIX connections.
3685 * channel_connect_ctx_free() must check ai_family
3686 * and use free() not freeaddirinfo() for AF_UNIX.
3687 */
3688 ai = xmalloc(sizeof(*ai) + sizeof(*sunaddr));
3689 memset(ai, 0, sizeof(*ai) + sizeof(*sunaddr));
3690 ai->ai_addr = (struct sockaddr *)(ai + 1);
3691 ai->ai_addrlen = sizeof(*sunaddr);
3692 ai->ai_family = AF_UNIX;
3693 ai->ai_socktype = SOCK_STREAM;
3694 ai->ai_protocol = PF_UNSPEC;
3695 sunaddr = (struct sockaddr_un *)ai->ai_addr;
3696 sunaddr->sun_family = AF_UNIX;
3697 strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path));
3698 cctx.aitop = ai;
3699 } else {
3700 memset(&hints, 0, sizeof(hints));
3701 hints.ai_family = IPv4or6;
3702 hints.ai_socktype = SOCK_STREAM;
3703 snprintf(strport, sizeof strport, "%d", port);
3704 if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) != 0) {
3705 error("connect_to %.100s: unknown host (%s)", name,
3706 ssh_gai_strerror(gaierr));
3707 return NULL;
3708 }
3392 } 3709 }
3393 3710
3394 cctx.host = xstrdup(host); 3711 cctx.host = xstrdup(name);
3395 cctx.port = port; 3712 cctx.port = port;
3396 cctx.ai = cctx.aitop; 3713 cctx.ai = cctx.aitop;
3397 3714
3398 if ((sock = connect_next(&cctx)) == -1) { 3715 if ((sock = connect_next(&cctx)) == -1) {
3399 error("connect to %.100s port %d failed: %s", 3716 error("connect to %.100s port %d failed: %s",
3400 host, port, strerror(errno)); 3717 name, port, strerror(errno));
3401 channel_connect_ctx_free(&cctx); 3718 channel_connect_ctx_free(&cctx);
3402 return NULL; 3719 return NULL;
3403 } 3720 }
@@ -3414,7 +3731,7 @@ channel_connect_by_listen_address(const char *listen_host,
3414 int i; 3731 int i;
3415 3732
3416 for (i = 0; i < num_permitted_opens; i++) { 3733 for (i = 0; i < num_permitted_opens; i++) {
3417 if (open_listen_match(&permitted_opens[i], listen_host, 3734 if (open_listen_match_tcpip(&permitted_opens[i], listen_host,
3418 listen_port, 1)) { 3735 listen_port, 1)) {
3419 return connect_to( 3736 return connect_to(
3420 permitted_opens[i].host_to_connect, 3737 permitted_opens[i].host_to_connect,
@@ -3426,9 +3743,26 @@ channel_connect_by_listen_address(const char *listen_host,
3426 return NULL; 3743 return NULL;
3427} 3744}
3428 3745
3746Channel *
3747channel_connect_by_listen_path(const char *path, char *ctype, char *rname)
3748{
3749 int i;
3750
3751 for (i = 0; i < num_permitted_opens; i++) {
3752 if (open_listen_match_streamlocal(&permitted_opens[i], path)) {
3753 return connect_to(
3754 permitted_opens[i].host_to_connect,
3755 permitted_opens[i].port_to_connect, ctype, rname);
3756 }
3757 }
3758 error("WARNING: Server requests forwarding for unknown path %.100s",
3759 path);
3760 return NULL;
3761}
3762
3429/* Check if connecting to that port is permitted and connect. */ 3763/* Check if connecting to that port is permitted and connect. */
3430Channel * 3764Channel *
3431channel_connect_to(const char *host, u_short port, char *ctype, char *rname) 3765channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname)
3432{ 3766{
3433 int i, permit, permit_adm = 1; 3767 int i, permit, permit_adm = 1;
3434 3768
@@ -3458,6 +3792,38 @@ channel_connect_to(const char *host, u_short port, char *ctype, char *rname)
3458 return connect_to(host, port, ctype, rname); 3792 return connect_to(host, port, ctype, rname);
3459} 3793}
3460 3794
3795/* Check if connecting to that path is permitted and connect. */
3796Channel *
3797channel_connect_to_path(const char *path, char *ctype, char *rname)
3798{
3799 int i, permit, permit_adm = 1;
3800
3801 permit = all_opens_permitted;
3802 if (!permit) {
3803 for (i = 0; i < num_permitted_opens; i++)
3804 if (open_match(&permitted_opens[i], path, PORT_STREAMLOCAL)) {
3805 permit = 1;
3806 break;
3807 }
3808 }
3809
3810 if (num_adm_permitted_opens > 0) {
3811 permit_adm = 0;
3812 for (i = 0; i < num_adm_permitted_opens; i++)
3813 if (open_match(&permitted_adm_opens[i], path, PORT_STREAMLOCAL)) {
3814 permit_adm = 1;
3815 break;
3816 }
3817 }
3818
3819 if (!permit || !permit_adm) {
3820 logit("Received request to connect to path %.100s, "
3821 "but the request was denied.", path);
3822 return NULL;
3823 }
3824 return connect_to(path, PORT_STREAMLOCAL, ctype, rname);
3825}
3826
3461void 3827void
3462channel_send_window_changes(void) 3828channel_send_window_changes(void)
3463{ 3829{
diff --git a/channels.h b/channels.h
index 4745b9a7d..a000c98e5 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.h,v 1.114 2014/06/27 16:41:56 markus Exp $ */ 1/* $OpenBSD: channels.h,v 1.115 2014/07/15 15:54:14 millert Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -56,7 +56,9 @@
56#define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */ 56#define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */
57#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */ 57#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */
58#define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */ 58#define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */
59#define SSH_CHANNEL_MAX_TYPE 18 59#define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */
60#define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */
61#define SSH_CHANNEL_MAX_TYPE 20
60 62
61#define CHANNEL_CANCEL_PORT_STATIC -1 63#define CHANNEL_CANCEL_PORT_STATIC -1
62 64
@@ -254,6 +256,8 @@ char *channel_open_message(void);
254int channel_find_open(void); 256int channel_find_open(void);
255 257
256/* tcp forwarding */ 258/* tcp forwarding */
259struct Forward;
260struct ForwardOptions;
257void channel_set_af(int af); 261void channel_set_af(int af);
258void channel_permit_all_opens(void); 262void channel_permit_all_opens(void);
259void channel_add_permitted_opens(char *, int); 263void channel_add_permitted_opens(char *, int);
@@ -263,19 +267,19 @@ void channel_update_permitted_opens(int, int);
263void channel_clear_permitted_opens(void); 267void channel_clear_permitted_opens(void);
264void channel_clear_adm_permitted_opens(void); 268void channel_clear_adm_permitted_opens(void);
265void channel_print_adm_permitted_opens(void); 269void channel_print_adm_permitted_opens(void);
266int channel_input_port_forward_request(int, int); 270int channel_input_port_forward_request(int, struct ForwardOptions *);
267Channel *channel_connect_to(const char *, u_short, char *, char *); 271Channel *channel_connect_to_port(const char *, u_short, char *, char *);
272Channel *channel_connect_to_path(const char *, char *, char *);
268Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); 273Channel *channel_connect_stdio_fwd(const char*, u_short, int, int);
269Channel *channel_connect_by_listen_address(const char *, u_short, 274Channel *channel_connect_by_listen_address(const char *, u_short,
270 char *, char *); 275 char *, char *);
271int channel_request_remote_forwarding(const char *, u_short, 276Channel *channel_connect_by_listen_path(const char *, char *, char *);
272 const char *, u_short); 277int channel_request_remote_forwarding(struct Forward *);
273int channel_setup_local_fwd_listener(const char *, u_short, 278int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *);
274 const char *, u_short, int); 279int channel_request_rforward_cancel(struct Forward *);
275int channel_request_rforward_cancel(const char *host, u_short port); 280int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *);
276int channel_setup_remote_fwd_listener(const char *, u_short, int *, int); 281int channel_cancel_rport_listener(struct Forward *);
277int channel_cancel_rport_listener(const char *, u_short); 282int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *);
278int channel_cancel_lport_listener(const char *, u_short, int, int);
279int permitopen_port(const char *); 283int permitopen_port(const char *);
280 284
281/* x11 forwarding */ 285/* x11 forwarding */
diff --git a/clientloop.c b/clientloop.c
index 02510e26d..397c96532 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.260 2014/06/27 16:41:56 markus Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.261 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -100,13 +100,13 @@
100#include "cipher.h" 100#include "cipher.h"
101#include "kex.h" 101#include "kex.h"
102#include "log.h" 102#include "log.h"
103#include "misc.h"
103#include "readconf.h" 104#include "readconf.h"
104#include "clientloop.h" 105#include "clientloop.h"
105#include "sshconnect.h" 106#include "sshconnect.h"
106#include "authfd.h" 107#include "authfd.h"
107#include "atomicio.h" 108#include "atomicio.h"
108#include "sshpty.h" 109#include "sshpty.h"
109#include "misc.h"
110#include "match.h" 110#include "match.h"
111#include "msg.h" 111#include "msg.h"
112#include "roaming.h" 112#include "roaming.h"
@@ -871,13 +871,11 @@ static void
871process_cmdline(void) 871process_cmdline(void)
872{ 872{
873 void (*handler)(int); 873 void (*handler)(int);
874 char *s, *cmd, *cancel_host; 874 char *s, *cmd;
875 int delete = 0, local = 0, remote = 0, dynamic = 0; 875 int ok, delete = 0, local = 0, remote = 0, dynamic = 0;
876 int cancel_port, ok; 876 struct Forward fwd;
877 Forward fwd;
878 877
879 memset(&fwd, 0, sizeof(fwd)); 878 memset(&fwd, 0, sizeof(fwd));
880 fwd.listen_host = fwd.connect_host = NULL;
881 879
882 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); 880 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
883 handler = signal(SIGINT, SIG_IGN); 881 handler = signal(SIGINT, SIG_IGN);
@@ -943,29 +941,20 @@ process_cmdline(void)
943 941
944 /* XXX update list of forwards in options */ 942 /* XXX update list of forwards in options */
945 if (delete) { 943 if (delete) {
946 cancel_port = 0; 944 /* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */
947 cancel_host = hpdelim(&s); /* may be NULL */ 945 if (!parse_forward(&fwd, s, 1, 0)) {
948 if (s != NULL) { 946 logit("Bad forwarding close specification.");
949 cancel_port = a2port(s);
950 cancel_host = cleanhostname(cancel_host);
951 } else {
952 cancel_port = a2port(cancel_host);
953 cancel_host = NULL;
954 }
955 if (cancel_port <= 0) {
956 logit("Bad forwarding close port");
957 goto out; 947 goto out;
958 } 948 }
959 if (remote) 949 if (remote)
960 ok = channel_request_rforward_cancel(cancel_host, 950 ok = channel_request_rforward_cancel(&fwd) == 0;
961 cancel_port) == 0;
962 else if (dynamic) 951 else if (dynamic)
963 ok = channel_cancel_lport_listener(cancel_host, 952 ok = channel_cancel_lport_listener(&fwd,
964 cancel_port, 0, options.gateway_ports) > 0; 953 0, &options.fwd_opts) > 0;
965 else 954 else
966 ok = channel_cancel_lport_listener(cancel_host, 955 ok = channel_cancel_lport_listener(&fwd,
967 cancel_port, CHANNEL_CANCEL_PORT_STATIC, 956 CHANNEL_CANCEL_PORT_STATIC,
968 options.gateway_ports) > 0; 957 &options.fwd_opts) > 0;
969 if (!ok) { 958 if (!ok) {
970 logit("Unkown port forwarding."); 959 logit("Unkown port forwarding.");
971 goto out; 960 goto out;
@@ -977,16 +966,13 @@ process_cmdline(void)
977 goto out; 966 goto out;
978 } 967 }
979 if (local || dynamic) { 968 if (local || dynamic) {
980 if (!channel_setup_local_fwd_listener(fwd.listen_host, 969 if (!channel_setup_local_fwd_listener(&fwd,
981 fwd.listen_port, fwd.connect_host, 970 &options.fwd_opts)) {
982 fwd.connect_port, options.gateway_ports)) {
983 logit("Port forwarding failed."); 971 logit("Port forwarding failed.");
984 goto out; 972 goto out;
985 } 973 }
986 } else { 974 } else {
987 if (channel_request_remote_forwarding(fwd.listen_host, 975 if (channel_request_remote_forwarding(&fwd) < 0) {
988 fwd.listen_port, fwd.connect_host,
989 fwd.connect_port) < 0) {
990 logit("Port forwarding failed."); 976 logit("Port forwarding failed.");
991 goto out; 977 goto out;
992 } 978 }
@@ -999,7 +985,9 @@ out:
999 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); 985 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1000 free(cmd); 986 free(cmd);
1001 free(fwd.listen_host); 987 free(fwd.listen_host);
988 free(fwd.listen_path);
1002 free(fwd.connect_host); 989 free(fwd.connect_host);
990 free(fwd.connect_path);
1003} 991}
1004 992
1005/* reasons to suppress output of an escape command in help output */ 993/* 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)
1845 originator_port = packet_get_int(); 1833 originator_port = packet_get_int();
1846 packet_check_eom(); 1834 packet_check_eom();
1847 1835
1848 debug("client_request_forwarded_tcpip: listen %s port %d, " 1836 debug("%s: listen %s port %d, originator %s port %d", __func__,
1849 "originator %s port %d", listen_address, listen_port, 1837 listen_address, listen_port, originator_address, originator_port);
1850 originator_address, originator_port);
1851 1838
1852 c = channel_connect_by_listen_address(listen_address, listen_port, 1839 c = channel_connect_by_listen_address(listen_address, listen_port,
1853 "forwarded-tcpip", originator_address); 1840 "forwarded-tcpip", originator_address);
@@ -1858,6 +1845,27 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
1858} 1845}
1859 1846
1860static Channel * 1847static Channel *
1848client_request_forwarded_streamlocal(const char *request_type, int rchan)
1849{
1850 Channel *c = NULL;
1851 char *listen_path;
1852
1853 /* Get the remote path. */
1854 listen_path = packet_get_string(NULL);
1855 /* XXX: Skip reserved field for now. */
1856 if (packet_get_string_ptr(NULL) == NULL)
1857 fatal("%s: packet_get_string_ptr failed", __func__);
1858 packet_check_eom();
1859
1860 debug("%s: %s", __func__, listen_path);
1861
1862 c = channel_connect_by_listen_path(listen_path,
1863 "forwarded-streamlocal@openssh.com", "forwarded-streamlocal");
1864 free(listen_path);
1865 return c;
1866}
1867
1868static Channel *
1861client_request_x11(const char *request_type, int rchan) 1869client_request_x11(const char *request_type, int rchan)
1862{ 1870{
1863 Channel *c = NULL; 1871 Channel *c = NULL;
@@ -1984,6 +1992,8 @@ client_input_channel_open(int type, u_int32_t seq, void *ctxt)
1984 1992
1985 if (strcmp(ctype, "forwarded-tcpip") == 0) { 1993 if (strcmp(ctype, "forwarded-tcpip") == 0) {
1986 c = client_request_forwarded_tcpip(ctype, rchan); 1994 c = client_request_forwarded_tcpip(ctype, rchan);
1995 } else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) {
1996 c = client_request_forwarded_streamlocal(ctype, rchan);
1987 } else if (strcmp(ctype, "x11") == 0) { 1997 } else if (strcmp(ctype, "x11") == 0) {
1988 c = client_request_x11(ctype, rchan); 1998 c = client_request_x11(ctype, rchan);
1989 } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { 1999 } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
diff --git a/misc.c b/misc.c
index 099c4ef80..739916ba4 100644
--- a/misc.c
+++ b/misc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: misc.c,v 1.93 2014/04/20 02:30:25 djm Exp $ */ 1/* $OpenBSD: misc.c,v 1.94 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2005,2006 Damien Miller. All rights reserved. 4 * Copyright (c) 2005,2006 Damien Miller. All rights reserved.
@@ -29,6 +29,7 @@
29#include <sys/types.h> 29#include <sys/types.h>
30#include <sys/ioctl.h> 30#include <sys/ioctl.h>
31#include <sys/socket.h> 31#include <sys/socket.h>
32#include <sys/un.h>
32#include <sys/param.h> 33#include <sys/param.h>
33 34
34#include <stdarg.h> 35#include <stdarg.h>
@@ -1056,6 +1057,52 @@ lowercase(char *s)
1056 for (; *s; s++) 1057 for (; *s; s++)
1057 *s = tolower((u_char)*s); 1058 *s = tolower((u_char)*s);
1058} 1059}
1060
1061int
1062unix_listener(const char *path, int backlog, int unlink_first)
1063{
1064 struct sockaddr_un sunaddr;
1065 int saved_errno, sock;
1066
1067 memset(&sunaddr, 0, sizeof(sunaddr));
1068 sunaddr.sun_family = AF_UNIX;
1069 if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) {
1070 error("%s: \"%s\" too long for Unix domain socket", __func__,
1071 path);
1072 errno = ENAMETOOLONG;
1073 return -1;
1074 }
1075
1076 sock = socket(PF_UNIX, SOCK_STREAM, 0);
1077 if (sock < 0) {
1078 saved_errno = errno;
1079 error("socket: %.100s", strerror(errno));
1080 errno = saved_errno;
1081 return -1;
1082 }
1083 if (unlink_first == 1) {
1084 if (unlink(path) != 0 && errno != ENOENT)
1085 error("unlink(%s): %.100s", path, strerror(errno));
1086 }
1087 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
1088 saved_errno = errno;
1089 error("bind: %.100s", strerror(errno));
1090 close(sock);
1091 error("%s: cannot bind to path: %s", __func__, path);
1092 errno = saved_errno;
1093 return -1;
1094 }
1095 if (listen(sock, backlog) < 0) {
1096 saved_errno = errno;
1097 error("listen: %.100s", strerror(errno));
1098 close(sock);
1099 unlink(path);
1100 error("%s: cannot listen on path: %s", __func__, path);
1101 errno = saved_errno;
1102 return -1;
1103 }
1104 return sock;
1105}
1059void 1106void
1060sock_set_v6only(int s) 1107sock_set_v6only(int s)
1061{ 1108{
diff --git a/misc.h b/misc.h
index 7b0c503a3..374c33ce1 100644
--- a/misc.h
+++ b/misc.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: misc.h,v 1.53 2014/05/02 03:27:54 djm Exp $ */ 1/* $OpenBSD: misc.h,v 1.54 2014/07/15 15:54:14 millert Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -15,6 +15,25 @@
15#ifndef _MISC_H 15#ifndef _MISC_H
16#define _MISC_H 16#define _MISC_H
17 17
18/* Data structure for representing a forwarding request. */
19struct Forward {
20 char *listen_host; /* Host (address) to listen on. */
21 int listen_port; /* Port to forward. */
22 char *listen_path; /* Path to bind domain socket. */
23 char *connect_host; /* Host to connect. */
24 int connect_port; /* Port to connect on connect_host. */
25 char *connect_path; /* Path to connect domain socket. */
26 int allocated_port; /* Dynamically allocated listen port */
27 int handle; /* Handle for dynamic listen ports */
28};
29
30/* Common server and client forwarding options. */
31struct ForwardOptions {
32 int gateway_ports; /* Allow remote connects to forwarded ports. */
33 mode_t streamlocal_bind_mask; /* umask for streamlocal binds */
34 int streamlocal_bind_unlink; /* unlink socket before bind */
35};
36
18/* misc.c */ 37/* misc.c */
19 38
20char *chop(char *); 39char *chop(char *);
@@ -37,6 +56,7 @@ void ms_subtract_diff(struct timeval *, int *);
37void ms_to_timeval(struct timeval *, int); 56void ms_to_timeval(struct timeval *, int);
38time_t monotime(void); 57time_t monotime(void);
39void lowercase(char *s); 58void lowercase(char *s);
59int unix_listener(const char *, int, int);
40 60
41void sock_set_v6only(int); 61void sock_set_v6only(int);
42 62
@@ -68,6 +88,9 @@ int tun_open(int, int);
68#define SSH_TUNID_ERR (SSH_TUNID_ANY - 1) 88#define SSH_TUNID_ERR (SSH_TUNID_ANY - 1)
69#define SSH_TUNID_MAX (SSH_TUNID_ANY - 2) 89#define SSH_TUNID_MAX (SSH_TUNID_ANY - 2)
70 90
91/* Fake port to indicate that host field is really a path. */
92#define PORT_STREAMLOCAL -2
93
71/* Functions to extract or store big-endian words of various sizes */ 94/* Functions to extract or store big-endian words of various sizes */
72u_int64_t get_u64(const void *) 95u_int64_t get_u64(const void *)
73 __attribute__((__bounded__( __minbytes__, 1, 8))); 96 __attribute__((__bounded__( __minbytes__, 1, 8)));
diff --git a/monitor.c b/monitor.c
index 68f4dbc71..72d71c4d3 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor.c,v 1.134 2014/06/24 01:13:21 djm Exp $ */ 1/* $OpenBSD: monitor.c,v 1.135 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 3 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4 * Copyright 2002 Markus Friedl <markus@openbsd.org> 4 * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -87,6 +87,7 @@
87#include "sshlogin.h" 87#include "sshlogin.h"
88#include "canohost.h" 88#include "canohost.h"
89#include "log.h" 89#include "log.h"
90#include "misc.h"
90#include "servconf.h" 91#include "servconf.h"
91#include "monitor.h" 92#include "monitor.h"
92#include "monitor_mm.h" 93#include "monitor_mm.h"
@@ -95,7 +96,6 @@
95#endif 96#endif
96#include "monitor_wrap.h" 97#include "monitor_wrap.h"
97#include "monitor_fdpass.h" 98#include "monitor_fdpass.h"
98#include "misc.h"
99#include "compat.h" 99#include "compat.h"
100#include "ssh2.h" 100#include "ssh2.h"
101#include "roaming.h" 101#include "roaming.h"
diff --git a/mux.c b/mux.c
index 784e942ba..5278ce4b6 100644
--- a/mux.c
+++ b/mux.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mux.c,v 1.45 2014/04/28 03:09:18 djm Exp $ */ 1/* $OpenBSD: mux.c,v 1.46 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -509,29 +509,33 @@ process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r)
509} 509}
510 510
511static char * 511static char *
512format_forward(u_int ftype, Forward *fwd) 512format_forward(u_int ftype, struct Forward *fwd)
513{ 513{
514 char *ret; 514 char *ret;
515 515
516 switch (ftype) { 516 switch (ftype) {
517 case MUX_FWD_LOCAL: 517 case MUX_FWD_LOCAL:
518 xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d", 518 xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d",
519 (fwd->listen_path != NULL) ? fwd->listen_path :
519 (fwd->listen_host == NULL) ? 520 (fwd->listen_host == NULL) ?
520 (options.gateway_ports ? "*" : "LOCALHOST") : 521 (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
521 fwd->listen_host, fwd->listen_port, 522 fwd->listen_host, fwd->listen_port,
523 (fwd->connect_path != NULL) ? fwd->connect_path :
522 fwd->connect_host, fwd->connect_port); 524 fwd->connect_host, fwd->connect_port);
523 break; 525 break;
524 case MUX_FWD_DYNAMIC: 526 case MUX_FWD_DYNAMIC:
525 xasprintf(&ret, "dynamic forward %.200s:%d -> *", 527 xasprintf(&ret, "dynamic forward %.200s:%d -> *",
526 (fwd->listen_host == NULL) ? 528 (fwd->listen_host == NULL) ?
527 (options.gateway_ports ? "*" : "LOCALHOST") : 529 (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
528 fwd->listen_host, fwd->listen_port); 530 fwd->listen_host, fwd->listen_port);
529 break; 531 break;
530 case MUX_FWD_REMOTE: 532 case MUX_FWD_REMOTE:
531 xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d", 533 xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d",
534 (fwd->listen_path != NULL) ? fwd->listen_path :
532 (fwd->listen_host == NULL) ? 535 (fwd->listen_host == NULL) ?
533 "LOCALHOST" : fwd->listen_host, 536 "LOCALHOST" : fwd->listen_host,
534 fwd->listen_port, 537 fwd->listen_port,
538 (fwd->connect_path != NULL) ? fwd->connect_path :
535 fwd->connect_host, fwd->connect_port); 539 fwd->connect_host, fwd->connect_port);
536 break; 540 break;
537 default: 541 default:
@@ -551,14 +555,18 @@ compare_host(const char *a, const char *b)
551} 555}
552 556
553static int 557static int
554compare_forward(Forward *a, Forward *b) 558compare_forward(struct Forward *a, struct Forward *b)
555{ 559{
556 if (!compare_host(a->listen_host, b->listen_host)) 560 if (!compare_host(a->listen_host, b->listen_host))
557 return 0; 561 return 0;
562 if (!compare_host(a->listen_path, b->listen_path))
563 return 0;
558 if (a->listen_port != b->listen_port) 564 if (a->listen_port != b->listen_port)
559 return 0; 565 return 0;
560 if (!compare_host(a->connect_host, b->connect_host)) 566 if (!compare_host(a->connect_host, b->connect_host))
561 return 0; 567 return 0;
568 if (!compare_host(a->connect_path, b->connect_path))
569 return 0;
562 if (a->connect_port != b->connect_port) 570 if (a->connect_port != b->connect_port)
563 return 0; 571 return 0;
564 572
@@ -570,7 +578,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
570{ 578{
571 struct mux_channel_confirm_ctx *fctx = ctxt; 579 struct mux_channel_confirm_ctx *fctx = ctxt;
572 char *failmsg = NULL; 580 char *failmsg = NULL;
573 Forward *rfwd; 581 struct Forward *rfwd;
574 Channel *c; 582 Channel *c;
575 Buffer out; 583 Buffer out;
576 584
@@ -587,7 +595,8 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
587 rfwd = &options.remote_forwards[fctx->fid]; 595 rfwd = &options.remote_forwards[fctx->fid];
588 debug("%s: %s for: listen %d, connect %s:%d", __func__, 596 debug("%s: %s for: listen %d, connect %s:%d", __func__,
589 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", 597 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
590 rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); 598 rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
599 rfwd->connect_host, rfwd->connect_port);
591 if (type == SSH2_MSG_REQUEST_SUCCESS) { 600 if (type == SSH2_MSG_REQUEST_SUCCESS) {
592 if (rfwd->listen_port == 0) { 601 if (rfwd->listen_port == 0) {
593 rfwd->allocated_port = packet_get_int(); 602 rfwd->allocated_port = packet_get_int();
@@ -607,8 +616,12 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
607 } else { 616 } else {
608 if (rfwd->listen_port == 0) 617 if (rfwd->listen_port == 0)
609 channel_update_permitted_opens(rfwd->handle, -1); 618 channel_update_permitted_opens(rfwd->handle, -1);
610 xasprintf(&failmsg, "remote port forwarding failed for " 619 if (rfwd->listen_path != NULL)
611 "listen port %d", rfwd->listen_port); 620 xasprintf(&failmsg, "remote port forwarding failed for "
621 "listen path %s", rfwd->listen_path);
622 else
623 xasprintf(&failmsg, "remote port forwarding failed for "
624 "listen port %d", rfwd->listen_port);
612 } 625 }
613 fail: 626 fail:
614 error("%s: %s", __func__, failmsg); 627 error("%s: %s", __func__, failmsg);
@@ -627,34 +640,46 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
627static int 640static int
628process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) 641process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
629{ 642{
630 Forward fwd; 643 struct Forward fwd;
631 char *fwd_desc = NULL; 644 char *fwd_desc = NULL;
645 char *listen_addr, *connect_addr;
632 u_int ftype; 646 u_int ftype;
633 u_int lport, cport; 647 u_int lport, cport;
634 int i, ret = 0, freefwd = 1; 648 int i, ret = 0, freefwd = 1;
635 649
636 fwd.listen_host = fwd.connect_host = NULL; 650 /* XXX - lport/cport check redundant */
637 if (buffer_get_int_ret(&ftype, m) != 0 || 651 if (buffer_get_int_ret(&ftype, m) != 0 ||
638 (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || 652 (listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
639 buffer_get_int_ret(&lport, m) != 0 || 653 buffer_get_int_ret(&lport, m) != 0 ||
640 (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || 654 (connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
641 buffer_get_int_ret(&cport, m) != 0 || 655 buffer_get_int_ret(&cport, m) != 0 ||
642 lport > 65535 || cport > 65535) { 656 (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
657 (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
643 error("%s: malformed message", __func__); 658 error("%s: malformed message", __func__);
644 ret = -1; 659 ret = -1;
645 goto out; 660 goto out;
646 } 661 }
647 fwd.listen_port = lport; 662 if (*listen_addr == '\0') {
648 fwd.connect_port = cport; 663 free(listen_addr);
649 if (*fwd.listen_host == '\0') { 664 listen_addr = NULL;
650 free(fwd.listen_host);
651 fwd.listen_host = NULL;
652 } 665 }
653 if (*fwd.connect_host == '\0') { 666 if (*connect_addr == '\0') {
654 free(fwd.connect_host); 667 free(connect_addr);
655 fwd.connect_host = NULL; 668 connect_addr = NULL;
656 } 669 }
657 670
671 memset(&fwd, 0, sizeof(fwd));
672 fwd.listen_port = lport;
673 if (fwd.listen_port == PORT_STREAMLOCAL)
674 fwd.listen_path = listen_addr;
675 else
676 fwd.listen_host = listen_addr;
677 fwd.connect_port = cport;
678 if (fwd.connect_port == PORT_STREAMLOCAL)
679 fwd.connect_path = connect_addr;
680 else
681 fwd.connect_host = connect_addr;
682
658 debug2("%s: channel %d: request %s", __func__, c->self, 683 debug2("%s: channel %d: request %s", __func__, c->self,
659 (fwd_desc = format_forward(ftype, &fwd))); 684 (fwd_desc = format_forward(ftype, &fwd)));
660 685
@@ -662,25 +687,30 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
662 ftype != MUX_FWD_DYNAMIC) { 687 ftype != MUX_FWD_DYNAMIC) {
663 logit("%s: invalid forwarding type %u", __func__, ftype); 688 logit("%s: invalid forwarding type %u", __func__, ftype);
664 invalid: 689 invalid:
665 free(fwd.listen_host); 690 free(listen_addr);
666 free(fwd.connect_host); 691 free(connect_addr);
667 buffer_put_int(r, MUX_S_FAILURE); 692 buffer_put_int(r, MUX_S_FAILURE);
668 buffer_put_int(r, rid); 693 buffer_put_int(r, rid);
669 buffer_put_cstring(r, "Invalid forwarding request"); 694 buffer_put_cstring(r, "Invalid forwarding request");
670 return 0; 695 return 0;
671 } 696 }
672 if (fwd.listen_port >= 65536) { 697 if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) {
698 logit("%s: streamlocal and dynamic forwards "
699 "are mutually exclusive", __func__);
700 goto invalid;
701 }
702 if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) {
673 logit("%s: invalid listen port %u", __func__, 703 logit("%s: invalid listen port %u", __func__,
674 fwd.listen_port); 704 fwd.listen_port);
675 goto invalid; 705 goto invalid;
676 } 706 }
677 if (fwd.connect_port >= 65536 || (ftype != MUX_FWD_DYNAMIC && 707 if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536)
678 ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { 708 || (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) {
679 logit("%s: invalid connect port %u", __func__, 709 logit("%s: invalid connect port %u", __func__,
680 fwd.connect_port); 710 fwd.connect_port);
681 goto invalid; 711 goto invalid;
682 } 712 }
683 if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL) { 713 if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) {
684 logit("%s: missing connect host", __func__); 714 logit("%s: missing connect host", __func__);
685 goto invalid; 715 goto invalid;
686 } 716 }
@@ -731,9 +761,8 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
731 } 761 }
732 762
733 if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { 763 if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
734 if (!channel_setup_local_fwd_listener(fwd.listen_host, 764 if (!channel_setup_local_fwd_listener(&fwd,
735 fwd.listen_port, fwd.connect_host, fwd.connect_port, 765 &options.fwd_opts)) {
736 options.gateway_ports)) {
737 fail: 766 fail:
738 logit("slave-requested %s failed", fwd_desc); 767 logit("slave-requested %s failed", fwd_desc);
739 buffer_put_int(r, MUX_S_FAILURE); 768 buffer_put_int(r, MUX_S_FAILURE);
@@ -746,8 +775,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
746 } else { 775 } else {
747 struct mux_channel_confirm_ctx *fctx; 776 struct mux_channel_confirm_ctx *fctx;
748 777
749 fwd.handle = channel_request_remote_forwarding(fwd.listen_host, 778 fwd.handle = channel_request_remote_forwarding(&fwd);
750 fwd.listen_port, fwd.connect_host, fwd.connect_port);
751 if (fwd.handle < 0) 779 if (fwd.handle < 0)
752 goto fail; 780 goto fail;
753 add_remote_forward(&options, &fwd); 781 add_remote_forward(&options, &fwd);
@@ -768,7 +796,9 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
768 free(fwd_desc); 796 free(fwd_desc);
769 if (freefwd) { 797 if (freefwd) {
770 free(fwd.listen_host); 798 free(fwd.listen_host);
799 free(fwd.listen_path);
771 free(fwd.connect_host); 800 free(fwd.connect_host);
801 free(fwd.connect_path);
772 } 802 }
773 return ret; 803 return ret;
774} 804}
@@ -776,36 +806,47 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
776static int 806static int
777process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) 807process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
778{ 808{
779 Forward fwd, *found_fwd; 809 struct Forward fwd, *found_fwd;
780 char *fwd_desc = NULL; 810 char *fwd_desc = NULL;
781 const char *error_reason = NULL; 811 const char *error_reason = NULL;
812 char *listen_addr = NULL, *connect_addr = NULL;
782 u_int ftype; 813 u_int ftype;
783 int i, listen_port, ret = 0; 814 int i, ret = 0;
784 u_int lport, cport; 815 u_int lport, cport;
785 816
786 fwd.listen_host = fwd.connect_host = NULL;
787 if (buffer_get_int_ret(&ftype, m) != 0 || 817 if (buffer_get_int_ret(&ftype, m) != 0 ||
788 (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || 818 (listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
789 buffer_get_int_ret(&lport, m) != 0 || 819 buffer_get_int_ret(&lport, m) != 0 ||
790 (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || 820 (connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
791 buffer_get_int_ret(&cport, m) != 0 || 821 buffer_get_int_ret(&cport, m) != 0 ||
792 lport > 65535 || cport > 65535) { 822 (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
823 (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
793 error("%s: malformed message", __func__); 824 error("%s: malformed message", __func__);
794 ret = -1; 825 ret = -1;
795 goto out; 826 goto out;
796 } 827 }
797 fwd.listen_port = lport;
798 fwd.connect_port = cport;
799 828
800 if (*fwd.listen_host == '\0') { 829 if (*listen_addr == '\0') {
801 free(fwd.listen_host); 830 free(listen_addr);
802 fwd.listen_host = NULL; 831 listen_addr = NULL;
803 } 832 }
804 if (*fwd.connect_host == '\0') { 833 if (*connect_addr == '\0') {
805 free(fwd.connect_host); 834 free(connect_addr);
806 fwd.connect_host = NULL; 835 connect_addr = NULL;
807 } 836 }
808 837
838 memset(&fwd, 0, sizeof(fwd));
839 fwd.listen_port = lport;
840 if (fwd.listen_port == PORT_STREAMLOCAL)
841 fwd.listen_path = listen_addr;
842 else
843 fwd.listen_host = listen_addr;
844 fwd.connect_port = cport;
845 if (fwd.connect_port == PORT_STREAMLOCAL)
846 fwd.connect_path = connect_addr;
847 else
848 fwd.connect_host = connect_addr;
849
809 debug2("%s: channel %d: request cancel %s", __func__, c->self, 850 debug2("%s: channel %d: request cancel %s", __func__, c->self,
810 (fwd_desc = format_forward(ftype, &fwd))); 851 (fwd_desc = format_forward(ftype, &fwd)));
811 852
@@ -840,18 +881,14 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
840 * This shouldn't fail unless we confused the host/port 881 * This shouldn't fail unless we confused the host/port
841 * between options.remote_forwards and permitted_opens. 882 * between options.remote_forwards and permitted_opens.
842 * However, for dynamic allocated listen ports we need 883 * However, for dynamic allocated listen ports we need
843 * to lookup the actual listen port. 884 * to use the actual listen port.
844 */ 885 */
845 listen_port = (fwd.listen_port == 0) ? 886 if (channel_request_rforward_cancel(found_fwd) == -1)
846 found_fwd->allocated_port : fwd.listen_port;
847 if (channel_request_rforward_cancel(fwd.listen_host,
848 listen_port) == -1)
849 error_reason = "port not in permitted opens"; 887 error_reason = "port not in permitted opens";
850 } else { /* local and dynamic forwards */ 888 } else { /* local and dynamic forwards */
851 /* Ditto */ 889 /* Ditto */
852 if (channel_cancel_lport_listener(fwd.listen_host, 890 if (channel_cancel_lport_listener(&fwd, fwd.connect_port,
853 fwd.listen_port, fwd.connect_port, 891 &options.fwd_opts) == -1)
854 options.gateway_ports) == -1)
855 error_reason = "port not found"; 892 error_reason = "port not found";
856 } 893 }
857 894
@@ -860,8 +897,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
860 buffer_put_int(r, rid); 897 buffer_put_int(r, rid);
861 898
862 free(found_fwd->listen_host); 899 free(found_fwd->listen_host);
900 free(found_fwd->listen_path);
863 free(found_fwd->connect_host); 901 free(found_fwd->connect_host);
902 free(found_fwd->connect_path);
864 found_fwd->listen_host = found_fwd->connect_host = NULL; 903 found_fwd->listen_host = found_fwd->connect_host = NULL;
904 found_fwd->listen_path = found_fwd->connect_path = NULL;
865 found_fwd->listen_port = found_fwd->connect_port = 0; 905 found_fwd->listen_port = found_fwd->connect_port = 0;
866 } else { 906 } else {
867 buffer_put_int(r, MUX_S_FAILURE); 907 buffer_put_int(r, MUX_S_FAILURE);
@@ -870,8 +910,8 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
870 } 910 }
871 out: 911 out:
872 free(fwd_desc); 912 free(fwd_desc);
873 free(fwd.listen_host); 913 free(listen_addr);
874 free(fwd.connect_host); 914 free(connect_addr);
875 915
876 return ret; 916 return ret;
877} 917}
@@ -1133,8 +1173,6 @@ mux_tty_alloc_failed(Channel *c)
1133void 1173void
1134muxserver_listen(void) 1174muxserver_listen(void)
1135{ 1175{
1136 struct sockaddr_un addr;
1137 socklen_t sun_len;
1138 mode_t old_umask; 1176 mode_t old_umask;
1139 char *orig_control_path = options.control_path; 1177 char *orig_control_path = options.control_path;
1140 char rbuf[16+1]; 1178 char rbuf[16+1];
@@ -1163,23 +1201,10 @@ muxserver_listen(void)
1163 xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf); 1201 xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf);
1164 debug3("%s: temporary control path %s", __func__, options.control_path); 1202 debug3("%s: temporary control path %s", __func__, options.control_path);
1165 1203
1166 memset(&addr, '\0', sizeof(addr));
1167 addr.sun_family = AF_UNIX;
1168 sun_len = offsetof(struct sockaddr_un, sun_path) +
1169 strlen(options.control_path) + 1;
1170
1171 if (strlcpy(addr.sun_path, options.control_path,
1172 sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) {
1173 error("ControlPath \"%s\" too long for Unix domain socket",
1174 options.control_path);
1175 goto disable_mux_master;
1176 }
1177
1178 if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
1179 fatal("%s socket(): %s", __func__, strerror(errno));
1180
1181 old_umask = umask(0177); 1204 old_umask = umask(0177);
1182 if (bind(muxserver_sock, (struct sockaddr *)&addr, sun_len) == -1) { 1205 muxserver_sock = unix_listener(options.control_path, 64, 0);
1206 umask(old_umask);
1207 if (muxserver_sock < 0) {
1183 if (errno == EINVAL || errno == EADDRINUSE) { 1208 if (errno == EINVAL || errno == EADDRINUSE) {
1184 error("ControlSocket %s already exists, " 1209 error("ControlSocket %s already exists, "
1185 "disabling multiplexing", options.control_path); 1210 "disabling multiplexing", options.control_path);
@@ -1193,13 +1218,11 @@ muxserver_listen(void)
1193 options.control_path = NULL; 1218 options.control_path = NULL;
1194 options.control_master = SSHCTL_MASTER_NO; 1219 options.control_master = SSHCTL_MASTER_NO;
1195 return; 1220 return;
1196 } else 1221 } else {
1197 fatal("%s bind(): %s", __func__, strerror(errno)); 1222 /* unix_listener() logs the error */
1223 cleanup_exit(255);
1224 }
1198 } 1225 }
1199 umask(old_umask);
1200
1201 if (listen(muxserver_sock, 64) == -1)
1202 fatal("%s listen(): %s", __func__, strerror(errno));
1203 1226
1204 /* Now atomically "move" the mux socket into position */ 1227 /* Now atomically "move" the mux socket into position */
1205 if (link(options.control_path, orig_control_path) != 0) { 1228 if (link(options.control_path, orig_control_path) != 0) {
@@ -1593,7 +1616,7 @@ mux_client_request_terminate(int fd)
1593} 1616}
1594 1617
1595static int 1618static int
1596mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) 1619mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
1597{ 1620{
1598 Buffer m; 1621 Buffer m;
1599 char *e, *fwd_desc; 1622 char *e, *fwd_desc;
@@ -1608,11 +1631,19 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd)
1608 buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD); 1631 buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD);
1609 buffer_put_int(&m, muxclient_request_id); 1632 buffer_put_int(&m, muxclient_request_id);
1610 buffer_put_int(&m, ftype); 1633 buffer_put_int(&m, ftype);
1611 buffer_put_cstring(&m, 1634 if (fwd->listen_path != NULL) {
1612 fwd->listen_host == NULL ? "" : fwd->listen_host); 1635 buffer_put_cstring(&m, fwd->listen_path);
1636 } else {
1637 buffer_put_cstring(&m,
1638 fwd->listen_host == NULL ? "" : fwd->listen_host);
1639 }
1613 buffer_put_int(&m, fwd->listen_port); 1640 buffer_put_int(&m, fwd->listen_port);
1614 buffer_put_cstring(&m, 1641 if (fwd->connect_path != NULL) {
1615 fwd->connect_host == NULL ? "" : fwd->connect_host); 1642 buffer_put_cstring(&m, fwd->connect_path);
1643 } else {
1644 buffer_put_cstring(&m,
1645 fwd->connect_host == NULL ? "" : fwd->connect_host);
1646 }
1616 buffer_put_int(&m, fwd->connect_port); 1647 buffer_put_int(&m, fwd->connect_port);
1617 1648
1618 if (mux_client_write_packet(fd, &m) != 0) 1649 if (mux_client_write_packet(fd, &m) != 0)
diff --git a/packet.c b/packet.c
index b97257986..6e7b87757 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.197 2014/06/24 01:13:21 djm Exp $ */ 1/* $OpenBSD: packet.c,v 1.198 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -66,7 +66,6 @@
66#include "crc32.h" 66#include "crc32.h"
67#include "compress.h" 67#include "compress.h"
68#include "deattack.h" 68#include "deattack.h"
69#include "channels.h"
70#include "compat.h" 69#include "compat.h"
71#include "ssh1.h" 70#include "ssh1.h"
72#include "ssh2.h" 71#include "ssh2.h"
@@ -77,6 +76,7 @@
77#include "log.h" 76#include "log.h"
78#include "canohost.h" 77#include "canohost.h"
79#include "misc.h" 78#include "misc.h"
79#include "channels.h"
80#include "ssh.h" 80#include "ssh.h"
81#include "ssherr.h" 81#include "ssherr.h"
82#include "roaming.h" 82#include "roaming.h"
diff --git a/platform.c b/platform.c
index 30fc60909..ee313da55 100644
--- a/platform.c
+++ b/platform.c
@@ -1,4 +1,4 @@
1/* $Id: platform.c,v 1.21 2014/01/21 01:59:29 tim Exp $ */ 1/* $Id: platform.c,v 1.22 2014/07/18 04:11:26 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Darren Tucker. All rights reserved. 4 * Copyright (c) 2006 Darren Tucker. All rights reserved.
@@ -25,6 +25,7 @@
25 25
26#include "log.h" 26#include "log.h"
27#include "buffer.h" 27#include "buffer.h"
28#include "misc.h"
28#include "servconf.h" 29#include "servconf.h"
29#include "key.h" 30#include "key.h"
30#include "hostfile.h" 31#include "hostfile.h"
diff --git a/readconf.c b/readconf.c
index a4ecf7a0b..7948ce1cd 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: readconf.c,v 1.219 2014/04/23 12:42:34 djm Exp $ */ 1/* $OpenBSD: readconf.c,v 1.220 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -18,6 +18,7 @@
18#include <sys/stat.h> 18#include <sys/stat.h>
19#include <sys/socket.h> 19#include <sys/socket.h>
20#include <sys/wait.h> 20#include <sys/wait.h>
21#include <sys/un.h>
21 22
22#include <netinet/in.h> 23#include <netinet/in.h>
23#include <netinet/in_systm.h> 24#include <netinet/in_systm.h>
@@ -48,9 +49,9 @@
48#include "pathnames.h" 49#include "pathnames.h"
49#include "log.h" 50#include "log.h"
50#include "key.h" 51#include "key.h"
52#include "misc.h"
51#include "readconf.h" 53#include "readconf.h"
52#include "match.h" 54#include "match.h"
53#include "misc.h"
54#include "buffer.h" 55#include "buffer.h"
55#include "kex.h" 56#include "kex.h"
56#include "mac.h" 57#include "mac.h"
@@ -149,6 +150,7 @@ typedef enum {
149 oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, 150 oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
150 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, 151 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
151 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, 152 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
153 oStreamLocalBindMask, oStreamLocalBindUnlink,
152 oIgnoredUnknownOption, oDeprecated, oUnsupported 154 oIgnoredUnknownOption, oDeprecated, oUnsupported
153} OpCodes; 155} OpCodes;
154 156
@@ -261,6 +263,8 @@ static struct {
261 { "canonicalizehostname", oCanonicalizeHostname }, 263 { "canonicalizehostname", oCanonicalizeHostname },
262 { "canonicalizemaxdots", oCanonicalizeMaxDots }, 264 { "canonicalizemaxdots", oCanonicalizeMaxDots },
263 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, 265 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
266 { "streamlocalbindmask", oStreamLocalBindMask },
267 { "streamlocalbindunlink", oStreamLocalBindUnlink },
264 { "ignoreunknown", oIgnoreUnknown }, 268 { "ignoreunknown", oIgnoreUnknown },
265 269
266 { NULL, oBadOption } 270 { NULL, oBadOption }
@@ -272,12 +276,13 @@ static struct {
272 */ 276 */
273 277
274void 278void
275add_local_forward(Options *options, const Forward *newfwd) 279add_local_forward(Options *options, const struct Forward *newfwd)
276{ 280{
277 Forward *fwd; 281 struct Forward *fwd;
278#ifndef NO_IPPORT_RESERVED_CONCEPT 282#ifndef NO_IPPORT_RESERVED_CONCEPT
279 extern uid_t original_real_uid; 283 extern uid_t original_real_uid;
280 if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) 284 if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 &&
285 newfwd->listen_path == NULL)
281 fatal("Privileged ports can only be forwarded by root."); 286 fatal("Privileged ports can only be forwarded by root.");
282#endif 287#endif
283 options->local_forwards = xrealloc(options->local_forwards, 288 options->local_forwards = xrealloc(options->local_forwards,
@@ -287,8 +292,10 @@ add_local_forward(Options *options, const Forward *newfwd)
287 292
288 fwd->listen_host = newfwd->listen_host; 293 fwd->listen_host = newfwd->listen_host;
289 fwd->listen_port = newfwd->listen_port; 294 fwd->listen_port = newfwd->listen_port;
295 fwd->listen_path = newfwd->listen_path;
290 fwd->connect_host = newfwd->connect_host; 296 fwd->connect_host = newfwd->connect_host;
291 fwd->connect_port = newfwd->connect_port; 297 fwd->connect_port = newfwd->connect_port;
298 fwd->connect_path = newfwd->connect_path;
292} 299}
293 300
294/* 301/*
@@ -297,9 +304,9 @@ add_local_forward(Options *options, const Forward *newfwd)
297 */ 304 */
298 305
299void 306void
300add_remote_forward(Options *options, const Forward *newfwd) 307add_remote_forward(Options *options, const struct Forward *newfwd)
301{ 308{
302 Forward *fwd; 309 struct Forward *fwd;
303 310
304 options->remote_forwards = xrealloc(options->remote_forwards, 311 options->remote_forwards = xrealloc(options->remote_forwards,
305 options->num_remote_forwards + 1, 312 options->num_remote_forwards + 1,
@@ -308,8 +315,10 @@ add_remote_forward(Options *options, const Forward *newfwd)
308 315
309 fwd->listen_host = newfwd->listen_host; 316 fwd->listen_host = newfwd->listen_host;
310 fwd->listen_port = newfwd->listen_port; 317 fwd->listen_port = newfwd->listen_port;
318 fwd->listen_path = newfwd->listen_path;
311 fwd->connect_host = newfwd->connect_host; 319 fwd->connect_host = newfwd->connect_host;
312 fwd->connect_port = newfwd->connect_port; 320 fwd->connect_port = newfwd->connect_port;
321 fwd->connect_path = newfwd->connect_path;
313 fwd->handle = newfwd->handle; 322 fwd->handle = newfwd->handle;
314 fwd->allocated_port = 0; 323 fwd->allocated_port = 0;
315} 324}
@@ -321,7 +330,9 @@ clear_forwardings(Options *options)
321 330
322 for (i = 0; i < options->num_local_forwards; i++) { 331 for (i = 0; i < options->num_local_forwards; i++) {
323 free(options->local_forwards[i].listen_host); 332 free(options->local_forwards[i].listen_host);
333 free(options->local_forwards[i].listen_path);
324 free(options->local_forwards[i].connect_host); 334 free(options->local_forwards[i].connect_host);
335 free(options->local_forwards[i].connect_path);
325 } 336 }
326 if (options->num_local_forwards > 0) { 337 if (options->num_local_forwards > 0) {
327 free(options->local_forwards); 338 free(options->local_forwards);
@@ -330,7 +341,9 @@ clear_forwardings(Options *options)
330 options->num_local_forwards = 0; 341 options->num_local_forwards = 0;
331 for (i = 0; i < options->num_remote_forwards; i++) { 342 for (i = 0; i < options->num_remote_forwards; i++) {
332 free(options->remote_forwards[i].listen_host); 343 free(options->remote_forwards[i].listen_host);
344 free(options->remote_forwards[i].listen_path);
333 free(options->remote_forwards[i].connect_host); 345 free(options->remote_forwards[i].connect_host);
346 free(options->remote_forwards[i].connect_path);
334 } 347 }
335 if (options->num_remote_forwards > 0) { 348 if (options->num_remote_forwards > 0) {
336 free(options->remote_forwards); 349 free(options->remote_forwards);
@@ -715,7 +728,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host,
715 LogLevel *log_level_ptr; 728 LogLevel *log_level_ptr;
716 long long val64; 729 long long val64;
717 size_t len; 730 size_t len;
718 Forward fwd; 731 struct Forward fwd;
719 const struct multistate *multistate_ptr; 732 const struct multistate *multistate_ptr;
720 struct allowed_cname *cname; 733 struct allowed_cname *cname;
721 734
@@ -805,7 +818,7 @@ parse_time:
805 goto parse_time; 818 goto parse_time;
806 819
807 case oGatewayPorts: 820 case oGatewayPorts:
808 intptr = &options->gateway_ports; 821 intptr = &options->fwd_opts.gateway_ports;
809 goto parse_flag; 822 goto parse_flag;
810 823
811 case oExitOnForwardFailure: 824 case oExitOnForwardFailure:
@@ -1405,6 +1418,21 @@ parse_int:
1405 intptr = &options->canonicalize_fallback_local; 1418 intptr = &options->canonicalize_fallback_local;
1406 goto parse_flag; 1419 goto parse_flag;
1407 1420
1421 case oStreamLocalBindMask:
1422 arg = strdelim(&s);
1423 if (!arg || *arg == '\0')
1424 fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
1425 /* Parse mode in octal format */
1426 value = strtol(arg, &endofnumber, 8);
1427 if (arg == endofnumber || value < 0 || value > 0777)
1428 fatal("%.200s line %d: Bad mask.", filename, linenum);
1429 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
1430 break;
1431
1432 case oStreamLocalBindUnlink:
1433 intptr = &options->fwd_opts.streamlocal_bind_unlink;
1434 goto parse_flag;
1435
1408 case oDeprecated: 1436 case oDeprecated:
1409 debug("%s line %d: Deprecated option \"%s\"", 1437 debug("%s line %d: Deprecated option \"%s\"",
1410 filename, linenum, keyword); 1438 filename, linenum, keyword);
@@ -1502,7 +1530,9 @@ initialize_options(Options * options)
1502 options->forward_x11_timeout = -1; 1530 options->forward_x11_timeout = -1;
1503 options->exit_on_forward_failure = -1; 1531 options->exit_on_forward_failure = -1;
1504 options->xauth_location = NULL; 1532 options->xauth_location = NULL;
1505 options->gateway_ports = -1; 1533 options->fwd_opts.gateway_ports = -1;
1534 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
1535 options->fwd_opts.streamlocal_bind_unlink = -1;
1506 options->use_privileged_port = -1; 1536 options->use_privileged_port = -1;
1507 options->rsa_authentication = -1; 1537 options->rsa_authentication = -1;
1508 options->pubkey_authentication = -1; 1538 options->pubkey_authentication = -1;
@@ -1615,8 +1645,12 @@ fill_default_options(Options * options)
1615 options->exit_on_forward_failure = 0; 1645 options->exit_on_forward_failure = 0;
1616 if (options->xauth_location == NULL) 1646 if (options->xauth_location == NULL)
1617 options->xauth_location = _PATH_XAUTH; 1647 options->xauth_location = _PATH_XAUTH;
1618 if (options->gateway_ports == -1) 1648 if (options->fwd_opts.gateway_ports == -1)
1619 options->gateway_ports = 0; 1649 options->fwd_opts.gateway_ports = 0;
1650 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
1651 options->fwd_opts.streamlocal_bind_mask = 0177;
1652 if (options->fwd_opts.streamlocal_bind_unlink == -1)
1653 options->fwd_opts.streamlocal_bind_unlink = 0;
1620 if (options->use_privileged_port == -1) 1654 if (options->use_privileged_port == -1)
1621 options->use_privileged_port = 0; 1655 options->use_privileged_port = 0;
1622 if (options->rsa_authentication == -1) 1656 if (options->rsa_authentication == -1)
@@ -1768,22 +1802,92 @@ fill_default_options(Options * options)
1768 /* options->preferred_authentications will be set in ssh */ 1802 /* options->preferred_authentications will be set in ssh */
1769} 1803}
1770 1804
1805struct fwdarg {
1806 char *arg;
1807 int ispath;
1808};
1809
1810/*
1811 * parse_fwd_field
1812 * parses the next field in a port forwarding specification.
1813 * sets fwd to the parsed field and advances p past the colon
1814 * or sets it to NULL at end of string.
1815 * returns 0 on success, else non-zero.
1816 */
1817static int
1818parse_fwd_field(char **p, struct fwdarg *fwd)
1819{
1820 char *ep, *cp = *p;
1821 int ispath = 0;
1822
1823 if (*cp == '\0') {
1824 *p = NULL;
1825 return -1; /* end of string */
1826 }
1827
1828 /*
1829 * A field escaped with square brackets is used literally.
1830 * XXX - allow ']' to be escaped via backslash?
1831 */
1832 if (*cp == '[') {
1833 /* find matching ']' */
1834 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
1835 if (*ep == '/')
1836 ispath = 1;
1837 }
1838 /* no matching ']' or not at end of field. */
1839 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
1840 return -1;
1841 /* NUL terminate the field and advance p past the colon */
1842 *ep++ = '\0';
1843 if (*ep != '\0')
1844 *ep++ = '\0';
1845 fwd->arg = cp + 1;
1846 fwd->ispath = ispath;
1847 *p = ep;
1848 return 0;
1849 }
1850
1851 for (cp = *p; *cp != '\0'; cp++) {
1852 switch (*cp) {
1853 case '\\':
1854 memmove(cp, cp + 1, strlen(cp + 1) + 1);
1855 cp++;
1856 break;
1857 case '/':
1858 ispath = 1;
1859 break;
1860 case ':':
1861 *cp++ = '\0';
1862 goto done;
1863 }
1864 }
1865done:
1866 fwd->arg = *p;
1867 fwd->ispath = ispath;
1868 *p = cp;
1869 return 0;
1870}
1871
1771/* 1872/*
1772 * parse_forward 1873 * parse_forward
1773 * parses a string containing a port forwarding specification of the form: 1874 * parses a string containing a port forwarding specification of the form:
1774 * dynamicfwd == 0 1875 * dynamicfwd == 0
1775 * [listenhost:]listenport:connecthost:connectport 1876 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
1877 * listenpath:connectpath
1776 * dynamicfwd == 1 1878 * dynamicfwd == 1
1777 * [listenhost:]listenport 1879 * [listenhost:]listenport
1778 * returns number of arguments parsed or zero on error 1880 * returns number of arguments parsed or zero on error
1779 */ 1881 */
1780int 1882int
1781parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 1883parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1782{ 1884{
1885 struct fwdarg fwdargs[4];
1886 char *p, *cp;
1783 int i; 1887 int i;
1784 char *p, *cp, *fwdarg[4];
1785 1888
1786 memset(fwd, '\0', sizeof(*fwd)); 1889 memset(fwd, 0, sizeof(*fwd));
1890 memset(fwdargs, 0, sizeof(fwdargs));
1787 1891
1788 cp = p = xstrdup(fwdspec); 1892 cp = p = xstrdup(fwdspec);
1789 1893
@@ -1791,39 +1895,70 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1791 while (isspace((u_char)*cp)) 1895 while (isspace((u_char)*cp))
1792 cp++; 1896 cp++;
1793 1897
1794 for (i = 0; i < 4; ++i) 1898 for (i = 0; i < 4; ++i) {
1795 if ((fwdarg[i] = hpdelim(&cp)) == NULL) 1899 if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
1796 break; 1900 break;
1901 }
1797 1902
1798 /* Check for trailing garbage */ 1903 /* Check for trailing garbage */
1799 if (cp != NULL) 1904 if (cp != NULL && *cp != '\0') {
1800 i = 0; /* failure */ 1905 i = 0; /* failure */
1906 }
1801 1907
1802 switch (i) { 1908 switch (i) {
1803 case 1: 1909 case 1:
1804 fwd->listen_host = NULL; 1910 if (fwdargs[0].ispath) {
1805 fwd->listen_port = a2port(fwdarg[0]); 1911 fwd->listen_path = xstrdup(fwdargs[0].arg);
1912 fwd->listen_port = PORT_STREAMLOCAL;
1913 } else {
1914 fwd->listen_host = NULL;
1915 fwd->listen_port = a2port(fwdargs[0].arg);
1916 }
1806 fwd->connect_host = xstrdup("socks"); 1917 fwd->connect_host = xstrdup("socks");
1807 break; 1918 break;
1808 1919
1809 case 2: 1920 case 2:
1810 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1921 if (fwdargs[0].ispath && fwdargs[1].ispath) {
1811 fwd->listen_port = a2port(fwdarg[1]); 1922 fwd->listen_path = xstrdup(fwdargs[0].arg);
1812 fwd->connect_host = xstrdup("socks"); 1923 fwd->listen_port = PORT_STREAMLOCAL;
1924 fwd->connect_path = xstrdup(fwdargs[1].arg);
1925 fwd->connect_port = PORT_STREAMLOCAL;
1926 } else if (fwdargs[1].ispath) {
1927 fwd->listen_host = NULL;
1928 fwd->listen_port = a2port(fwdargs[0].arg);
1929 fwd->connect_path = xstrdup(fwdargs[1].arg);
1930 fwd->connect_port = PORT_STREAMLOCAL;
1931 } else {
1932 fwd->listen_host = xstrdup(fwdargs[0].arg);
1933 fwd->listen_port = a2port(fwdargs[1].arg);
1934 fwd->connect_host = xstrdup("socks");
1935 }
1813 break; 1936 break;
1814 1937
1815 case 3: 1938 case 3:
1816 fwd->listen_host = NULL; 1939 if (fwdargs[0].ispath) {
1817 fwd->listen_port = a2port(fwdarg[0]); 1940 fwd->listen_path = xstrdup(fwdargs[0].arg);
1818 fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); 1941 fwd->listen_port = PORT_STREAMLOCAL;
1819 fwd->connect_port = a2port(fwdarg[2]); 1942 fwd->connect_host = xstrdup(fwdargs[1].arg);
1943 fwd->connect_port = a2port(fwdargs[2].arg);
1944 } else if (fwdargs[2].ispath) {
1945 fwd->listen_host = xstrdup(fwdargs[0].arg);
1946 fwd->listen_port = a2port(fwdargs[1].arg);
1947 fwd->connect_path = xstrdup(fwdargs[2].arg);
1948 fwd->connect_port = PORT_STREAMLOCAL;
1949 } else {
1950 fwd->listen_host = NULL;
1951 fwd->listen_port = a2port(fwdargs[0].arg);
1952 fwd->connect_host = xstrdup(fwdargs[1].arg);
1953 fwd->connect_port = a2port(fwdargs[2].arg);
1954 }
1820 break; 1955 break;
1821 1956
1822 case 4: 1957 case 4:
1823 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1958 fwd->listen_host = xstrdup(fwdargs[0].arg);
1824 fwd->listen_port = a2port(fwdarg[1]); 1959 fwd->listen_port = a2port(fwdargs[1].arg);
1825 fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); 1960 fwd->connect_host = xstrdup(fwdargs[2].arg);
1826 fwd->connect_port = a2port(fwdarg[3]); 1961 fwd->connect_port = a2port(fwdargs[3].arg);
1827 break; 1962 break;
1828 default: 1963 default:
1829 i = 0; /* failure */ 1964 i = 0; /* failure */
@@ -1835,29 +1970,42 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1835 if (!(i == 1 || i == 2)) 1970 if (!(i == 1 || i == 2))
1836 goto fail_free; 1971 goto fail_free;
1837 } else { 1972 } else {
1838 if (!(i == 3 || i == 4)) 1973 if (!(i == 3 || i == 4)) {
1839 goto fail_free; 1974 if (fwd->connect_path == NULL &&
1840 if (fwd->connect_port <= 0) 1975 fwd->listen_path == NULL)
1976 goto fail_free;
1977 }
1978 if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
1841 goto fail_free; 1979 goto fail_free;
1842 } 1980 }
1843 1981
1844 if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) 1982 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
1983 (!remotefwd && fwd->listen_port == 0))
1845 goto fail_free; 1984 goto fail_free;
1846
1847 if (fwd->connect_host != NULL && 1985 if (fwd->connect_host != NULL &&
1848 strlen(fwd->connect_host) >= NI_MAXHOST) 1986 strlen(fwd->connect_host) >= NI_MAXHOST)
1849 goto fail_free; 1987 goto fail_free;
1988 /* XXX - if connecting to a remote socket, max sun len may not match this host */
1989 if (fwd->connect_path != NULL &&
1990 strlen(fwd->connect_path) >= PATH_MAX_SUN)
1991 goto fail_free;
1850 if (fwd->listen_host != NULL && 1992 if (fwd->listen_host != NULL &&
1851 strlen(fwd->listen_host) >= NI_MAXHOST) 1993 strlen(fwd->listen_host) >= NI_MAXHOST)
1852 goto fail_free; 1994 goto fail_free;
1853 1995 if (fwd->listen_path != NULL &&
1996 strlen(fwd->listen_path) >= PATH_MAX_SUN)
1997 goto fail_free;
1854 1998
1855 return (i); 1999 return (i);
1856 2000
1857 fail_free: 2001 fail_free:
1858 free(fwd->connect_host); 2002 free(fwd->connect_host);
1859 fwd->connect_host = NULL; 2003 fwd->connect_host = NULL;
2004 free(fwd->connect_path);
2005 fwd->connect_path = NULL;
1860 free(fwd->listen_host); 2006 free(fwd->listen_host);
1861 fwd->listen_host = NULL; 2007 fwd->listen_host = NULL;
2008 free(fwd->listen_path);
2009 fwd->listen_path = NULL;
1862 return (0); 2010 return (0);
1863} 2011}
diff --git a/readconf.h b/readconf.h
index 75e3f8f7a..0b9cb777a 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: readconf.h,v 1.101 2014/02/23 20:11:36 djm Exp $ */ 1/* $OpenBSD: readconf.h,v 1.102 2014/07/15 15:54:14 millert Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -16,21 +16,12 @@
16#ifndef READCONF_H 16#ifndef READCONF_H
17#define READCONF_H 17#define READCONF_H
18 18
19/* Data structure for representing a forwarding request. */
20
21typedef struct {
22 char *listen_host; /* Host (address) to listen on. */
23 int listen_port; /* Port to forward. */
24 char *connect_host; /* Host to connect. */
25 int connect_port; /* Port to connect on connect_host. */
26 int allocated_port; /* Dynamically allocated listen port */
27 int handle; /* Handle for dynamic listen ports */
28} Forward;
29/* Data structure for representing option data. */ 19/* Data structure for representing option data. */
30 20
31#define MAX_SEND_ENV 256 21#define MAX_SEND_ENV 256
32#define SSH_MAX_HOSTS_FILES 32 22#define SSH_MAX_HOSTS_FILES 32
33#define MAX_CANON_DOMAINS 32 23#define MAX_CANON_DOMAINS 32
24#define PATH_MAX_SUN (sizeof((struct sockaddr_un *)0)->sun_path)
34 25
35struct allowed_cname { 26struct allowed_cname {
36 char *source_list; 27 char *source_list;
@@ -44,7 +35,7 @@ typedef struct {
44 int forward_x11_trusted; /* Trust Forward X11 display. */ 35 int forward_x11_trusted; /* Trust Forward X11 display. */
45 int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */ 36 int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */
46 char *xauth_location; /* Location for xauth program */ 37 char *xauth_location; /* Location for xauth program */
47 int gateway_ports; /* Allow remote connects to forwarded ports. */ 38 struct ForwardOptions fwd_opts; /* forwarding options */
48 int use_privileged_port; /* Don't use privileged port if false. */ 39 int use_privileged_port; /* Don't use privileged port if false. */
49 int rhosts_rsa_authentication; /* Try rhosts with RSA 40 int rhosts_rsa_authentication; /* Try rhosts with RSA
50 * authentication. */ 41 * authentication. */
@@ -106,11 +97,11 @@ typedef struct {
106 97
107 /* Local TCP/IP forward requests. */ 98 /* Local TCP/IP forward requests. */
108 int num_local_forwards; 99 int num_local_forwards;
109 Forward *local_forwards; 100 struct Forward *local_forwards;
110 101
111 /* Remote TCP/IP forward requests. */ 102 /* Remote TCP/IP forward requests. */
112 int num_remote_forwards; 103 int num_remote_forwards;
113 Forward *remote_forwards; 104 struct Forward *remote_forwards;
114 int clear_forwardings; 105 int clear_forwardings;
115 106
116 int enable_ssh_keysign; 107 int enable_ssh_keysign;
@@ -181,12 +172,12 @@ int process_config_line(Options *, struct passwd *, const char *, char *,
181 const char *, int, int *, int); 172 const char *, int, int *, int);
182int read_config_file(const char *, struct passwd *, const char *, 173int read_config_file(const char *, struct passwd *, const char *,
183 Options *, int); 174 Options *, int);
184int parse_forward(Forward *, const char *, int, int); 175int parse_forward(struct Forward *, const char *, int, int);
185int default_ssh_port(void); 176int default_ssh_port(void);
186int option_clear_or_none(const char *); 177int option_clear_or_none(const char *);
187 178
188void add_local_forward(Options *, const Forward *); 179void add_local_forward(Options *, const struct Forward *);
189void add_remote_forward(Options *, const Forward *); 180void add_remote_forward(Options *, const struct Forward *);
190void add_identity_file(Options *, const char *, const char *, int); 181void add_identity_file(Options *, const char *, const char *, int);
191 182
192#endif /* READCONF_H */ 183#endif /* READCONF_H */
diff --git a/sandbox-systrace.c b/sandbox-systrace.c
index 08cb650bd..a74dc4f9d 100644
--- a/sandbox-systrace.c
+++ b/sandbox-systrace.c
@@ -60,7 +60,7 @@ static const struct sandbox_policy preauth_policy[] = {
60 { SYS___sysctl, SYSTR_POLICY_PERMIT }, 60 { SYS___sysctl, SYSTR_POLICY_PERMIT },
61#endif 61#endif
62 62
63 { SYS_sendsyslog, SYSTR_POLICY_PERMIT }, 63// { SYS_sendsyslog, SYSTR_POLICY_PERMIT },
64 { SYS_close, SYSTR_POLICY_PERMIT }, 64 { SYS_close, SYSTR_POLICY_PERMIT },
65 { SYS_exit, SYSTR_POLICY_PERMIT }, 65 { SYS_exit, SYSTR_POLICY_PERMIT },
66 { SYS_getpid, SYSTR_POLICY_PERMIT }, 66 { SYS_getpid, SYSTR_POLICY_PERMIT },
diff --git a/servconf.c b/servconf.c
index 331716c8f..b7f329447 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
1 1
2/* $OpenBSD: servconf.c,v 1.250 2014/07/03 22:40:43 djm Exp $ */ 2/* $OpenBSD: servconf.c,v 1.251 2014/07/15 15:54:14 millert Exp $ */
3/* 3/*
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved 5 * All rights reserved
@@ -39,10 +39,10 @@
39#include "ssh.h" 39#include "ssh.h"
40#include "log.h" 40#include "log.h"
41#include "buffer.h" 41#include "buffer.h"
42#include "misc.h"
42#include "servconf.h" 43#include "servconf.h"
43#include "compat.h" 44#include "compat.h"
44#include "pathnames.h" 45#include "pathnames.h"
45#include "misc.h"
46#include "cipher.h" 46#include "cipher.h"
47#include "key.h" 47#include "key.h"
48#include "kex.h" 48#include "kex.h"
@@ -120,6 +120,7 @@ initialize_server_options(ServerOptions *options)
120 options->rekey_limit = -1; 120 options->rekey_limit = -1;
121 options->rekey_interval = -1; 121 options->rekey_interval = -1;
122 options->allow_tcp_forwarding = -1; 122 options->allow_tcp_forwarding = -1;
123 options->allow_streamlocal_forwarding = -1;
123 options->allow_agent_forwarding = -1; 124 options->allow_agent_forwarding = -1;
124 options->num_allow_users = 0; 125 options->num_allow_users = 0;
125 options->num_deny_users = 0; 126 options->num_deny_users = 0;
@@ -129,7 +130,9 @@ initialize_server_options(ServerOptions *options)
129 options->macs = NULL; 130 options->macs = NULL;
130 options->kex_algorithms = NULL; 131 options->kex_algorithms = NULL;
131 options->protocol = SSH_PROTO_UNKNOWN; 132 options->protocol = SSH_PROTO_UNKNOWN;
132 options->gateway_ports = -1; 133 options->fwd_opts.gateway_ports = -1;
134 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
135 options->fwd_opts.streamlocal_bind_unlink = -1;
133 options->num_subsystems = 0; 136 options->num_subsystems = 0;
134 options->max_startups_begin = -1; 137 options->max_startups_begin = -1;
135 options->max_startups_rate = -1; 138 options->max_startups_rate = -1;
@@ -269,10 +272,12 @@ fill_default_server_options(ServerOptions *options)
269 options->rekey_interval = 0; 272 options->rekey_interval = 0;
270 if (options->allow_tcp_forwarding == -1) 273 if (options->allow_tcp_forwarding == -1)
271 options->allow_tcp_forwarding = FORWARD_ALLOW; 274 options->allow_tcp_forwarding = FORWARD_ALLOW;
275 if (options->allow_streamlocal_forwarding == -1)
276 options->allow_streamlocal_forwarding = FORWARD_ALLOW;
272 if (options->allow_agent_forwarding == -1) 277 if (options->allow_agent_forwarding == -1)
273 options->allow_agent_forwarding = 1; 278 options->allow_agent_forwarding = 1;
274 if (options->gateway_ports == -1) 279 if (options->fwd_opts.gateway_ports == -1)
275 options->gateway_ports = 0; 280 options->fwd_opts.gateway_ports = 0;
276 if (options->max_startups == -1) 281 if (options->max_startups == -1)
277 options->max_startups = 100; 282 options->max_startups = 100;
278 if (options->max_startups_rate == -1) 283 if (options->max_startups_rate == -1)
@@ -303,6 +308,10 @@ fill_default_server_options(ServerOptions *options)
303 options->ip_qos_bulk = IPTOS_THROUGHPUT; 308 options->ip_qos_bulk = IPTOS_THROUGHPUT;
304 if (options->version_addendum == NULL) 309 if (options->version_addendum == NULL)
305 options->version_addendum = xstrdup(""); 310 options->version_addendum = xstrdup("");
311 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
312 options->fwd_opts.streamlocal_bind_mask = 0177;
313 if (options->fwd_opts.streamlocal_bind_unlink == -1)
314 options->fwd_opts.streamlocal_bind_unlink = 0;
306 /* Turn privilege separation on by default */ 315 /* Turn privilege separation on by default */
307 if (use_privsep == -1) 316 if (use_privsep == -1)
308 use_privsep = PRIVSEP_NOSANDBOX; 317 use_privsep = PRIVSEP_NOSANDBOX;
@@ -351,6 +360,8 @@ typedef enum {
351 sKexAlgorithms, sIPQoS, sVersionAddendum, 360 sKexAlgorithms, sIPQoS, sVersionAddendum,
352 sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, 361 sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
353 sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, 362 sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
363 sStreamLocalBindMask, sStreamLocalBindUnlink,
364 sAllowStreamLocalForwarding,
354 sDeprecated, sUnsupported 365 sDeprecated, sUnsupported
355} ServerOpCodes; 366} ServerOpCodes;
356 367
@@ -478,6 +489,9 @@ static struct {
478 { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, 489 { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
479 { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, 490 { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
480 { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, 491 { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
492 { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
493 { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
494 { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
481 { NULL, sBadOption, 0 } 495 { NULL, sBadOption, 0 }
482}; 496};
483 497
@@ -1195,7 +1209,7 @@ process_server_config_line(ServerOptions *options, char *line,
1195 break; 1209 break;
1196 1210
1197 case sGatewayPorts: 1211 case sGatewayPorts:
1198 intptr = &options->gateway_ports; 1212 intptr = &options->fwd_opts.gateway_ports;
1199 multistate_ptr = multistate_gatewayports; 1213 multistate_ptr = multistate_gatewayports;
1200 goto parse_multistate; 1214 goto parse_multistate;
1201 1215
@@ -1230,6 +1244,11 @@ process_server_config_line(ServerOptions *options, char *line,
1230 multistate_ptr = multistate_tcpfwd; 1244 multistate_ptr = multistate_tcpfwd;
1231 goto parse_multistate; 1245 goto parse_multistate;
1232 1246
1247 case sAllowStreamLocalForwarding:
1248 intptr = &options->allow_streamlocal_forwarding;
1249 multistate_ptr = multistate_tcpfwd;
1250 goto parse_multistate;
1251
1233 case sAllowAgentForwarding: 1252 case sAllowAgentForwarding:
1234 intptr = &options->allow_agent_forwarding; 1253 intptr = &options->allow_agent_forwarding;
1235 goto parse_flag; 1254 goto parse_flag;
@@ -1628,6 +1647,22 @@ process_server_config_line(ServerOptions *options, char *line,
1628 } 1647 }
1629 return 0; 1648 return 0;
1630 1649
1650 case sStreamLocalBindMask:
1651 arg = strdelim(&cp);
1652 if (!arg || *arg == '\0')
1653 fatal("%s line %d: missing StreamLocalBindMask argument.",
1654 filename, linenum);
1655 /* Parse mode in octal format */
1656 value = strtol(arg, &p, 8);
1657 if (arg == p || value < 0 || value > 0777)
1658 fatal("%s line %d: Bad mask.", filename, linenum);
1659 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
1660 break;
1661
1662 case sStreamLocalBindUnlink:
1663 intptr = &options->fwd_opts.streamlocal_bind_unlink;
1664 goto parse_flag;
1665
1631 case sDeprecated: 1666 case sDeprecated:
1632 logit("%s line %d: Deprecated option %s", 1667 logit("%s line %d: Deprecated option %s",
1633 filename, linenum, arg); 1668 filename, linenum, arg);
@@ -1767,9 +1802,10 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
1767 M_CP_INTOPT(permit_empty_passwd); 1802 M_CP_INTOPT(permit_empty_passwd);
1768 1803
1769 M_CP_INTOPT(allow_tcp_forwarding); 1804 M_CP_INTOPT(allow_tcp_forwarding);
1805 M_CP_INTOPT(allow_streamlocal_forwarding);
1770 M_CP_INTOPT(allow_agent_forwarding); 1806 M_CP_INTOPT(allow_agent_forwarding);
1771 M_CP_INTOPT(permit_tun); 1807 M_CP_INTOPT(permit_tun);
1772 M_CP_INTOPT(gateway_ports); 1808 M_CP_INTOPT(fwd_opts.gateway_ports);
1773 M_CP_INTOPT(x11_display_offset); 1809 M_CP_INTOPT(x11_display_offset);
1774 M_CP_INTOPT(x11_forwarding); 1810 M_CP_INTOPT(x11_forwarding);
1775 M_CP_INTOPT(x11_use_localhost); 1811 M_CP_INTOPT(x11_use_localhost);
@@ -1867,6 +1903,8 @@ fmt_intarg(ServerOpCodes code, int val)
1867 return fmt_multistate_int(val, multistate_privsep); 1903 return fmt_multistate_int(val, multistate_privsep);
1868 case sAllowTcpForwarding: 1904 case sAllowTcpForwarding:
1869 return fmt_multistate_int(val, multistate_tcpfwd); 1905 return fmt_multistate_int(val, multistate_tcpfwd);
1906 case sAllowStreamLocalForwarding:
1907 return fmt_multistate_int(val, multistate_tcpfwd);
1870 case sProtocol: 1908 case sProtocol:
1871 switch (val) { 1909 switch (val) {
1872 case SSH_PROTO_1: 1910 case SSH_PROTO_1:
@@ -2023,9 +2061,10 @@ dump_config(ServerOptions *o)
2023 dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); 2061 dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
2024 dump_cfg_fmtint(sUseLogin, o->use_login); 2062 dump_cfg_fmtint(sUseLogin, o->use_login);
2025 dump_cfg_fmtint(sCompression, o->compression); 2063 dump_cfg_fmtint(sCompression, o->compression);
2026 dump_cfg_fmtint(sGatewayPorts, o->gateway_ports); 2064 dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
2027 dump_cfg_fmtint(sUseDNS, o->use_dns); 2065 dump_cfg_fmtint(sUseDNS, o->use_dns);
2028 dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); 2066 dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
2067 dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
2029 dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); 2068 dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
2030 2069
2031 /* string arguments */ 2070 /* string arguments */
diff --git a/servconf.h b/servconf.h
index f2a177649..766db3a3d 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: servconf.h,v 1.113 2014/07/03 22:40:43 djm Exp $ */ 1/* $OpenBSD: servconf.h,v 1.114 2014/07/15 15:54:14 millert Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -92,7 +92,7 @@ typedef struct {
92 char *macs; /* Supported SSH2 macs. */ 92 char *macs; /* Supported SSH2 macs. */
93 char *kex_algorithms; /* SSH2 kex methods in order of preference. */ 93 char *kex_algorithms; /* SSH2 kex methods in order of preference. */
94 int protocol; /* Supported protocol versions. */ 94 int protocol; /* Supported protocol versions. */
95 int gateway_ports; /* If true, allow remote connects to forwarded ports. */ 95 struct ForwardOptions fwd_opts; /* forwarding options */
96 SyslogFacility log_facility; /* Facility for system logging. */ 96 SyslogFacility log_facility; /* Facility for system logging. */
97 LogLevel log_level; /* Level for system logging. */ 97 LogLevel log_level; /* Level for system logging. */
98 int rhosts_rsa_authentication; /* If true, permit rhosts RSA 98 int rhosts_rsa_authentication; /* If true, permit rhosts RSA
@@ -124,6 +124,7 @@ typedef struct {
124 int use_login; /* If true, login(1) is used */ 124 int use_login; /* If true, login(1) is used */
125 int compression; /* If true, compression is allowed */ 125 int compression; /* If true, compression is allowed */
126 int allow_tcp_forwarding; /* One of FORWARD_* */ 126 int allow_tcp_forwarding; /* One of FORWARD_* */
127 int allow_streamlocal_forwarding; /* One of FORWARD_* */
127 int allow_agent_forwarding; 128 int allow_agent_forwarding;
128 u_int num_allow_users; 129 u_int num_allow_users;
129 char *allow_users[MAX_ALLOW_USERS]; 130 char *allow_users[MAX_ALLOW_USERS];
diff --git a/serverloop.c b/serverloop.c
index 6c4b2b512..7a80da55a 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: serverloop.c,v 1.171 2014/04/29 13:10:30 djm Exp $ */ 1/* $OpenBSD: serverloop.c,v 1.172 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -61,6 +61,7 @@
61#include "packet.h" 61#include "packet.h"
62#include "buffer.h" 62#include "buffer.h"
63#include "log.h" 63#include "log.h"
64#include "misc.h"
64#include "servconf.h" 65#include "servconf.h"
65#include "canohost.h" 66#include "canohost.h"
66#include "sshpty.h" 67#include "sshpty.h"
@@ -77,7 +78,6 @@
77#include "dispatch.h" 78#include "dispatch.h"
78#include "auth-options.h" 79#include "auth-options.h"
79#include "serverloop.h" 80#include "serverloop.h"
80#include "misc.h"
81#include "roaming.h" 81#include "roaming.h"
82 82
83extern ServerOptions options; 83extern ServerOptions options;
@@ -970,7 +970,7 @@ server_request_direct_tcpip(void)
970 /* XXX fine grained permissions */ 970 /* XXX fine grained permissions */
971 if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && 971 if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
972 !no_port_forwarding_flag) { 972 !no_port_forwarding_flag) {
973 c = channel_connect_to(target, target_port, 973 c = channel_connect_to_port(target, target_port,
974 "direct-tcpip", "direct-tcpip"); 974 "direct-tcpip", "direct-tcpip");
975 } else { 975 } else {
976 logit("refused local port forward: " 976 logit("refused local port forward: "
@@ -985,6 +985,38 @@ server_request_direct_tcpip(void)
985} 985}
986 986
987static Channel * 987static Channel *
988server_request_direct_streamlocal(void)
989{
990 Channel *c = NULL;
991 char *target, *originator;
992 u_short originator_port;
993
994 target = packet_get_string(NULL);
995 originator = packet_get_string(NULL);
996 originator_port = packet_get_int();
997 packet_check_eom();
998
999 debug("server_request_direct_streamlocal: originator %s port %d, target %s",
1000 originator, originator_port, target);
1001
1002 /* XXX fine grained permissions */
1003 if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 &&
1004 !no_port_forwarding_flag) {
1005 c = channel_connect_to_path(target,
1006 "direct-streamlocal@openssh.com", "direct-streamlocal");
1007 } else {
1008 logit("refused streamlocal port forward: "
1009 "originator %s port %d, target %s",
1010 originator, originator_port, target);
1011 }
1012
1013 free(originator);
1014 free(target);
1015
1016 return c;
1017}
1018
1019static Channel *
988server_request_tun(void) 1020server_request_tun(void)
989{ 1021{
990 Channel *c = NULL; 1022 Channel *c = NULL;
@@ -1081,6 +1113,8 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
1081 c = server_request_session(); 1113 c = server_request_session();
1082 } else if (strcmp(ctype, "direct-tcpip") == 0) { 1114 } else if (strcmp(ctype, "direct-tcpip") == 0) {
1083 c = server_request_direct_tcpip(); 1115 c = server_request_direct_tcpip();
1116 } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) {
1117 c = server_request_direct_streamlocal();
1084 } else if (strcmp(ctype, "tun@openssh.com") == 0) { 1118 } else if (strcmp(ctype, "tun@openssh.com") == 0) {
1085 c = server_request_tun(); 1119 c = server_request_tun();
1086 } 1120 }
@@ -1125,47 +1159,74 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
1125 /* -R style forwarding */ 1159 /* -R style forwarding */
1126 if (strcmp(rtype, "tcpip-forward") == 0) { 1160 if (strcmp(rtype, "tcpip-forward") == 0) {
1127 struct passwd *pw; 1161 struct passwd *pw;
1128 char *listen_address; 1162 struct Forward fwd;
1129 u_short listen_port;
1130 1163
1131 pw = the_authctxt->pw; 1164 pw = the_authctxt->pw;
1132 if (pw == NULL || !the_authctxt->valid) 1165 if (pw == NULL || !the_authctxt->valid)
1133 fatal("server_input_global_request: no/invalid user"); 1166 fatal("server_input_global_request: no/invalid user");
1134 listen_address = packet_get_string(NULL); 1167 memset(&fwd, 0, sizeof(fwd));
1135 listen_port = (u_short)packet_get_int(); 1168 fwd.listen_host = packet_get_string(NULL);
1169 fwd.listen_port = (u_short)packet_get_int();
1136 debug("server_input_global_request: tcpip-forward listen %s port %d", 1170 debug("server_input_global_request: tcpip-forward listen %s port %d",
1137 listen_address, listen_port); 1171 fwd.listen_host, fwd.listen_port);
1138 1172
1139 /* check permissions */ 1173 /* check permissions */
1140 if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 || 1174 if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
1141 no_port_forwarding_flag || 1175 no_port_forwarding_flag ||
1142 (!want_reply && listen_port == 0) 1176 (!want_reply && fwd.listen_port == 0) ||
1143#ifndef NO_IPPORT_RESERVED_CONCEPT 1177#ifndef NO_IPPORT_RESERVED_CONCEPT
1144 || (listen_port != 0 && listen_port < IPPORT_RESERVED && 1178 (fwd.listen_port != 0 && fwd.listen_port < IPPORT_RESERVED &&
1145 pw->pw_uid != 0) 1179 pw->pw_uid != 0)
1146#endif 1180#endif
1147 ) { 1181 ) {
1148 success = 0; 1182 success = 0;
1149 packet_send_debug("Server has disabled port forwarding."); 1183 packet_send_debug("Server has disabled port forwarding.");
1150 } else { 1184 } else {
1151 /* Start listening on the port */ 1185 /* Start listening on the port */
1152 success = channel_setup_remote_fwd_listener( 1186 success = channel_setup_remote_fwd_listener(&fwd,
1153 listen_address, listen_port, 1187 &allocated_listen_port, &options.fwd_opts);
1154 &allocated_listen_port, options.gateway_ports);
1155 } 1188 }
1156 free(listen_address); 1189 free(fwd.listen_host);
1157 } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { 1190 } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
1158 char *cancel_address; 1191 struct Forward fwd;
1159 u_short cancel_port;
1160 1192
1161 cancel_address = packet_get_string(NULL); 1193 memset(&fwd, 0, sizeof(fwd));
1162 cancel_port = (u_short)packet_get_int(); 1194 fwd.listen_host = packet_get_string(NULL);
1195 fwd.listen_port = (u_short)packet_get_int();
1163 debug("%s: cancel-tcpip-forward addr %s port %d", __func__, 1196 debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
1164 cancel_address, cancel_port); 1197 fwd.listen_host, fwd.listen_port);
1198
1199 success = channel_cancel_rport_listener(&fwd);
1200 free(fwd.listen_host);
1201 } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) {
1202 struct Forward fwd;
1203
1204 memset(&fwd, 0, sizeof(fwd));
1205 fwd.listen_path = packet_get_string(NULL);
1206 debug("server_input_global_request: streamlocal-forward listen path %s",
1207 fwd.listen_path);
1208
1209 /* check permissions */
1210 if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0
1211 || no_port_forwarding_flag) {
1212 success = 0;
1213 packet_send_debug("Server has disabled port forwarding.");
1214 } else {
1215 /* Start listening on the socket */
1216 success = channel_setup_remote_fwd_listener(
1217 &fwd, NULL, &options.fwd_opts);
1218 }
1219 free(fwd.listen_path);
1220 } else if (strcmp(rtype, "cancel-streamlocal-forward@openssh.com") == 0) {
1221 struct Forward fwd;
1222
1223 memset(&fwd, 0, sizeof(fwd));
1224 fwd.listen_path = packet_get_string(NULL);
1225 debug("%s: cancel-streamlocal-forward path %s", __func__,
1226 fwd.listen_path);
1165 1227
1166 success = channel_cancel_rport_listener(cancel_address, 1228 success = channel_cancel_rport_listener(&fwd);
1167 cancel_port); 1229 free(fwd.listen_path);
1168 free(cancel_address);
1169 } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { 1230 } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
1170 no_more_sessions = 1; 1231 no_more_sessions = 1;
1171 success = 1; 1232 success = 1;
diff --git a/session.c b/session.c
index b5979dd91..3e96557b8 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: session.c,v 1.273 2014/07/03 22:40:43 djm Exp $ */ 1/* $OpenBSD: session.c,v 1.274 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 4 * All rights reserved
@@ -84,11 +84,11 @@
84#include "authfd.h" 84#include "authfd.h"
85#include "pathnames.h" 85#include "pathnames.h"
86#include "log.h" 86#include "log.h"
87#include "misc.h"
87#include "servconf.h" 88#include "servconf.h"
88#include "sshlogin.h" 89#include "sshlogin.h"
89#include "serverloop.h" 90#include "serverloop.h"
90#include "canohost.h" 91#include "canohost.h"
91#include "misc.h"
92#include "session.h" 92#include "session.h"
93#include "kex.h" 93#include "kex.h"
94#include "monitor_wrap.h" 94#include "monitor_wrap.h"
@@ -183,7 +183,6 @@ auth_input_request_forwarding(struct passwd * pw)
183{ 183{
184 Channel *nc; 184 Channel *nc;
185 int sock = -1; 185 int sock = -1;
186 struct sockaddr_un sunaddr;
187 186
188 if (auth_sock_name != NULL) { 187 if (auth_sock_name != NULL) {
189 error("authentication forwarding requested twice."); 188 error("authentication forwarding requested twice.");
@@ -209,33 +208,15 @@ auth_input_request_forwarding(struct passwd * pw)
209 xasprintf(&auth_sock_name, "%s/agent.%ld", 208 xasprintf(&auth_sock_name, "%s/agent.%ld",
210 auth_sock_dir, (long) getpid()); 209 auth_sock_dir, (long) getpid());
211 210
212 /* Create the socket. */ 211 /* Start a Unix listener on auth_sock_name. */
213 sock = socket(AF_UNIX, SOCK_STREAM, 0); 212 sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0);
214 if (sock < 0) {
215 error("socket: %.100s", strerror(errno));
216 restore_uid();
217 goto authsock_err;
218 }
219
220 /* Bind it to the name. */
221 memset(&sunaddr, 0, sizeof(sunaddr));
222 sunaddr.sun_family = AF_UNIX;
223 strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
224
225 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
226 error("bind: %.100s", strerror(errno));
227 restore_uid();
228 goto authsock_err;
229 }
230 213
231 /* Restore the privileged uid. */ 214 /* Restore the privileged uid. */
232 restore_uid(); 215 restore_uid();
233 216
234 /* Start listening on the socket. */ 217 /* Check for socket/bind/listen failure. */
235 if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { 218 if (sock < 0)
236 error("listen: %.100s", strerror(errno));
237 goto authsock_err; 219 goto authsock_err;
238 }
239 220
240 /* Allocate a channel for the authentication agent socket. */ 221 /* Allocate a channel for the authentication agent socket. */
241 nc = channel_new("auth socket", 222 nc = channel_new("auth socket",
@@ -274,6 +255,7 @@ do_authenticated(Authctxt *authctxt)
274 setproctitle("%s", authctxt->pw->pw_name); 255 setproctitle("%s", authctxt->pw->pw_name);
275 256
276 /* setup the channel layer */ 257 /* setup the channel layer */
258 /* XXX - streamlocal? */
277 if (no_port_forwarding_flag || 259 if (no_port_forwarding_flag ||
278 (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) 260 (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
279 channel_disable_adm_local_opens(); 261 channel_disable_adm_local_opens();
@@ -393,7 +375,7 @@ do_authenticated1(Authctxt *authctxt)
393 } 375 }
394 debug("Received TCP/IP port forwarding request."); 376 debug("Received TCP/IP port forwarding request.");
395 if (channel_input_port_forward_request(s->pw->pw_uid == 0, 377 if (channel_input_port_forward_request(s->pw->pw_uid == 0,
396 options.gateway_ports) < 0) { 378 &options.fwd_opts) < 0) {
397 debug("Port forwarding failed."); 379 debug("Port forwarding failed.");
398 break; 380 break;
399 } 381 }
diff --git a/ssh-agent.c b/ssh-agent.c
index f7a021364..26c1bd37e 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-agent.c,v 1.187 2014/07/03 03:11:03 djm Exp $ */ 1/* $OpenBSD: ssh-agent.c,v 1.188 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1038,11 +1038,9 @@ main(int ac, char **av)
1038 u_int nalloc; 1038 u_int nalloc;
1039 char *shell, *format, *pidstr, *agentsocket = NULL; 1039 char *shell, *format, *pidstr, *agentsocket = NULL;
1040 fd_set *readsetp = NULL, *writesetp = NULL; 1040 fd_set *readsetp = NULL, *writesetp = NULL;
1041 struct sockaddr_un sunaddr;
1042#ifdef HAVE_SETRLIMIT 1041#ifdef HAVE_SETRLIMIT
1043 struct rlimit rlim; 1042 struct rlimit rlim;
1044#endif 1043#endif
1045 int prev_mask;
1046 extern int optind; 1044 extern int optind;
1047 extern char *optarg; 1045 extern char *optarg;
1048 pid_t pid; 1046 pid_t pid;
@@ -1161,25 +1159,10 @@ main(int ac, char **av)
1161 * Create socket early so it will exist before command gets run from 1159 * Create socket early so it will exist before command gets run from
1162 * the parent. 1160 * the parent.
1163 */ 1161 */
1164 sock = socket(AF_UNIX, SOCK_STREAM, 0); 1162 sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0);
1165 if (sock < 0) { 1163 if (sock < 0) {
1166 perror("socket"); 1164 /* XXX - unix_listener() calls error() not perror() */
1167 *socket_name = '\0'; /* Don't unlink any existing file */
1168 cleanup_exit(1);
1169 }
1170 memset(&sunaddr, 0, sizeof(sunaddr));
1171 sunaddr.sun_family = AF_UNIX;
1172 strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
1173 prev_mask = umask(0177);
1174 if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) {
1175 perror("bind");
1176 *socket_name = '\0'; /* Don't unlink any existing file */ 1165 *socket_name = '\0'; /* Don't unlink any existing file */
1177 umask(prev_mask);
1178 cleanup_exit(1);
1179 }
1180 umask(prev_mask);
1181 if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
1182 perror("listen");
1183 cleanup_exit(1); 1166 cleanup_exit(1);
1184 } 1167 }
1185 1168
diff --git a/ssh.c b/ssh.c
index 54f1dbd0a..47375f5ea 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.405 2014/07/03 06:39:19 djm Exp $ */ 1/* $OpenBSD: ssh.c,v 1.406 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -96,9 +96,9 @@
96#include "dispatch.h" 96#include "dispatch.h"
97#include "clientloop.h" 97#include "clientloop.h"
98#include "log.h" 98#include "log.h"
99#include "misc.h"
99#include "readconf.h" 100#include "readconf.h"
100#include "sshconnect.h" 101#include "sshconnect.h"
101#include "misc.h"
102#include "kex.h" 102#include "kex.h"
103#include "mac.h" 103#include "mac.h"
104#include "sshpty.h" 104#include "sshpty.h"
@@ -423,7 +423,7 @@ main(int ac, char **av)
423 int timeout_ms; 423 int timeout_ms;
424 extern int optind, optreset; 424 extern int optind, optreset;
425 extern char *optarg; 425 extern char *optarg;
426 Forward fwd; 426 struct Forward fwd;
427 struct addrinfo *addrs = NULL; 427 struct addrinfo *addrs = NULL;
428 struct ssh_digest_ctx *md; 428 struct ssh_digest_ctx *md;
429 u_char conn_hash[SSH_DIGEST_MAX_LENGTH]; 429 u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
@@ -545,7 +545,7 @@ main(int ac, char **av)
545 options.forward_x11_trusted = 1; 545 options.forward_x11_trusted = 1;
546 break; 546 break;
547 case 'g': 547 case 'g':
548 options.gateway_ports = 1; 548 options.fwd_opts.gateway_ports = 1;
549 break; 549 break;
550 case 'O': 550 case 'O':
551 if (stdio_forward_host != NULL) 551 if (stdio_forward_host != NULL)
@@ -1305,15 +1305,17 @@ fork_postauth(void)
1305static void 1305static void
1306ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) 1306ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
1307{ 1307{
1308 Forward *rfwd = (Forward *)ctxt; 1308 struct Forward *rfwd = (struct Forward *)ctxt;
1309 1309
1310 /* XXX verbose() on failure? */ 1310 /* XXX verbose() on failure? */
1311 debug("remote forward %s for: listen %s%s%d, connect %s:%d", 1311 debug("remote forward %s for: listen %s%s%d, connect %s:%d",
1312 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", 1312 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1313 rfwd->listen_host == NULL ? "" : rfwd->listen_host, 1313 rfwd->listen_path ? rfwd->listen_path :
1314 rfwd->listen_host == NULL ? "" : ":", 1314 rfwd->listen_host ? rfwd->listen_host : "",
1315 rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); 1315 (rfwd->listen_path || rfwd->listen_host) ? ":" : "",
1316 if (rfwd->listen_port == 0) { 1316 rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
1317 rfwd->connect_host, rfwd->connect_port);
1318 if (rfwd->listen_path == NULL && rfwd->listen_port == 0) {
1317 if (type == SSH2_MSG_REQUEST_SUCCESS) { 1319 if (type == SSH2_MSG_REQUEST_SUCCESS) {
1318 rfwd->allocated_port = packet_get_int(); 1320 rfwd->allocated_port = packet_get_int();
1319 logit("Allocated port %u for remote forward to %s:%d", 1321 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)
1327 } 1329 }
1328 1330
1329 if (type == SSH2_MSG_REQUEST_FAILURE) { 1331 if (type == SSH2_MSG_REQUEST_FAILURE) {
1330 if (options.exit_on_forward_failure) 1332 if (options.exit_on_forward_failure) {
1331 fatal("Error: remote port forwarding failed for " 1333 if (rfwd->listen_path != NULL)
1332 "listen port %d", rfwd->listen_port); 1334 fatal("Error: remote port forwarding failed "
1333 else 1335 "for listen path %s", rfwd->listen_path);
1334 logit("Warning: remote port forwarding failed for " 1336 else
1335 "listen port %d", rfwd->listen_port); 1337 fatal("Error: remote port forwarding failed "
1338 "for listen port %d", rfwd->listen_port);
1339 } else {
1340 if (rfwd->listen_path != NULL)
1341 logit("Warning: remote port forwarding failed "
1342 "for listen path %s", rfwd->listen_path);
1343 else
1344 logit("Warning: remote port forwarding failed "
1345 "for listen port %d", rfwd->listen_port);
1346 }
1336 } 1347 }
1337 if (++remote_forward_confirms_received == options.num_remote_forwards) { 1348 if (++remote_forward_confirms_received == options.num_remote_forwards) {
1338 debug("All remote forwarding requests processed"); 1349 debug("All remote forwarding requests processed");
@@ -1380,18 +1391,18 @@ ssh_init_forwarding(void)
1380 for (i = 0; i < options.num_local_forwards; i++) { 1391 for (i = 0; i < options.num_local_forwards; i++) {
1381 debug("Local connections to %.200s:%d forwarded to remote " 1392 debug("Local connections to %.200s:%d forwarded to remote "
1382 "address %.200s:%d", 1393 "address %.200s:%d",
1394 (options.local_forwards[i].listen_path != NULL) ?
1395 options.local_forwards[i].listen_path :
1383 (options.local_forwards[i].listen_host == NULL) ? 1396 (options.local_forwards[i].listen_host == NULL) ?
1384 (options.gateway_ports ? "*" : "LOCALHOST") : 1397 (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
1385 options.local_forwards[i].listen_host, 1398 options.local_forwards[i].listen_host,
1386 options.local_forwards[i].listen_port, 1399 options.local_forwards[i].listen_port,
1400 (options.local_forwards[i].connect_path != NULL) ?
1401 options.local_forwards[i].connect_path :
1387 options.local_forwards[i].connect_host, 1402 options.local_forwards[i].connect_host,
1388 options.local_forwards[i].connect_port); 1403 options.local_forwards[i].connect_port);
1389 success += channel_setup_local_fwd_listener( 1404 success += channel_setup_local_fwd_listener(
1390 options.local_forwards[i].listen_host, 1405 &options.local_forwards[i], &options.fwd_opts);
1391 options.local_forwards[i].listen_port,
1392 options.local_forwards[i].connect_host,
1393 options.local_forwards[i].connect_port,
1394 options.gateway_ports);
1395 } 1406 }
1396 if (i > 0 && success != i && options.exit_on_forward_failure) 1407 if (i > 0 && success != i && options.exit_on_forward_failure)
1397 fatal("Could not request local forwarding."); 1408 fatal("Could not request local forwarding.");
@@ -1402,17 +1413,18 @@ ssh_init_forwarding(void)
1402 for (i = 0; i < options.num_remote_forwards; i++) { 1413 for (i = 0; i < options.num_remote_forwards; i++) {
1403 debug("Remote connections from %.200s:%d forwarded to " 1414 debug("Remote connections from %.200s:%d forwarded to "
1404 "local address %.200s:%d", 1415 "local address %.200s:%d",
1416 (options.remote_forwards[i].listen_path != NULL) ?
1417 options.remote_forwards[i].listen_path :
1405 (options.remote_forwards[i].listen_host == NULL) ? 1418 (options.remote_forwards[i].listen_host == NULL) ?
1406 "LOCALHOST" : options.remote_forwards[i].listen_host, 1419 "LOCALHOST" : options.remote_forwards[i].listen_host,
1407 options.remote_forwards[i].listen_port, 1420 options.remote_forwards[i].listen_port,
1421 (options.remote_forwards[i].connect_path != NULL) ?
1422 options.remote_forwards[i].connect_path :
1408 options.remote_forwards[i].connect_host, 1423 options.remote_forwards[i].connect_host,
1409 options.remote_forwards[i].connect_port); 1424 options.remote_forwards[i].connect_port);
1410 options.remote_forwards[i].handle = 1425 options.remote_forwards[i].handle =
1411 channel_request_remote_forwarding( 1426 channel_request_remote_forwarding(
1412 options.remote_forwards[i].listen_host, 1427 &options.remote_forwards[i]);
1413 options.remote_forwards[i].listen_port,
1414 options.remote_forwards[i].connect_host,
1415 options.remote_forwards[i].connect_port);
1416 if (options.remote_forwards[i].handle < 0) { 1428 if (options.remote_forwards[i].handle < 0) {
1417 if (options.exit_on_forward_failure) 1429 if (options.exit_on_forward_failure)
1418 fatal("Could not request remote forwarding."); 1430 fatal("Could not request remote forwarding.");
diff --git a/ssh_config.5 b/ssh_config.5
index 71b9bdcc5..f9ede7a31 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: ssh_config.5,v 1.190 2014/07/07 08:19:12 djm Exp $ 36.\" $OpenBSD: ssh_config.5,v 1.191 2014/07/15 15:54:14 millert Exp $
37.Dd $Mdocdate: July 7 2014 $ 37.Dd $Mdocdate: July 15 2014 $
38.Dt SSH_CONFIG 5 38.Dt SSH_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -1303,6 +1303,33 @@ channel to request a response from the server.
1303The default 1303The default
1304is 0, indicating that these messages will not be sent to the server. 1304is 0, indicating that these messages will not be sent to the server.
1305This option applies to protocol version 2 only. 1305This option applies to protocol version 2 only.
1306.It Cm StreamLocalBindMask
1307Sets the octal file creation mode mask
1308.Pq umask
1309used when creating a Unix-domain socket file for local or remote
1310port forwarding.
1311This option is only used for port forwarding to a Unix-domain socket file.
1312.Pp
1313The default value is 0177, which creates a Unix-domain socket file that is
1314readable and writable only by the owner.
1315Note that not all operating systems honor the file mode on Unix-domain
1316socket files.
1317.It Cm StreamLocalBindUnlink
1318Specifies whether to remove an existing Unix-domain socket file for local
1319or remote port forwarding before creating a new one.
1320If the socket file already exists and
1321.Cm StreamLocalBindUnlink
1322is not enabled,
1323.Nm ssh
1324will be unable to forward the port to the Unix-domain socket file.
1325This option is only used for port forwarding to a Unix-domain socket file.
1326.Pp
1327The argument must be
1328.Dq yes
1329or
1330.Dq no .
1331The default is
1332.Dq no .
1306.It Cm StrictHostKeyChecking 1333.It Cm StrictHostKeyChecking
1307If this flag is set to 1334If this flag is set to
1308.Dq yes , 1335.Dq yes ,
diff --git a/sshconnect.c b/sshconnect.c
index 799c8d00c..ac09eae67 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect.c,v 1.250 2014/07/03 22:23:46 djm Exp $ */ 1/* $OpenBSD: sshconnect.c,v 1.251 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -54,9 +54,9 @@
54#include "sshconnect.h" 54#include "sshconnect.h"
55#include "hostfile.h" 55#include "hostfile.h"
56#include "log.h" 56#include "log.h"
57#include "misc.h"
57#include "readconf.h" 58#include "readconf.h"
58#include "atomicio.h" 59#include "atomicio.h"
59#include "misc.h"
60#include "dns.h" 60#include "dns.h"
61#include "roaming.h" 61#include "roaming.h"
62#include "monitor_fdpass.h" 62#include "monitor_fdpass.h"
diff --git a/sshconnect1.c b/sshconnect1.c
index 62a7bd17f..dd12a3af2 100644
--- a/sshconnect1.c
+++ b/sshconnect1.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect1.c,v 1.75 2014/06/24 01:13:21 djm Exp $ */ 1/* $OpenBSD: sshconnect1.c,v 1.76 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -38,11 +38,11 @@
38#include "kex.h" 38#include "kex.h"
39#include "uidswap.h" 39#include "uidswap.h"
40#include "log.h" 40#include "log.h"
41#include "misc.h"
41#include "readconf.h" 42#include "readconf.h"
42#include "authfd.h" 43#include "authfd.h"
43#include "sshconnect.h" 44#include "sshconnect.h"
44#include "authfile.h" 45#include "authfile.h"
45#include "misc.h"
46#include "canohost.h" 46#include "canohost.h"
47#include "hostfile.h" 47#include "hostfile.h"
48#include "auth.h" 48#include "auth.h"
diff --git a/sshconnect2.c b/sshconnect2.c
index eb1b0ae3c..68f7f4fdd 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.209 2014/06/24 01:13:21 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.210 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Damien Miller. All rights reserved. 4 * Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -61,8 +61,8 @@
61#include "dh.h" 61#include "dh.h"
62#include "authfd.h" 62#include "authfd.h"
63#include "log.h" 63#include "log.h"
64#include "readconf.h"
65#include "misc.h" 64#include "misc.h"
65#include "readconf.h"
66#include "match.h" 66#include "match.h"
67#include "dispatch.h" 67#include "dispatch.h"
68#include "canohost.h" 68#include "canohost.h"
diff --git a/sshd.c b/sshd.c
index 67eb66a11..481d00155 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.427 2014/06/24 01:13:21 djm Exp $ */ 1/* $OpenBSD: sshd.c,v 1.428 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -93,6 +93,7 @@
93#include "packet.h" 93#include "packet.h"
94#include "log.h" 94#include "log.h"
95#include "buffer.h" 95#include "buffer.h"
96#include "misc.h"
96#include "servconf.h" 97#include "servconf.h"
97#include "uidswap.h" 98#include "uidswap.h"
98#include "compat.h" 99#include "compat.h"
@@ -108,7 +109,6 @@
108#include "hostfile.h" 109#include "hostfile.h"
109#include "auth.h" 110#include "auth.h"
110#include "authfd.h" 111#include "authfd.h"
111#include "misc.h"
112#include "msg.h" 112#include "msg.h"
113#include "dispatch.h" 113#include "dispatch.h"
114#include "channels.h" 114#include "channels.h"
diff --git a/sshd_config.5 b/sshd_config.5
index 06fd62de7..f92084857 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: sshd_config.5,v 1.174 2014/07/03 22:40:43 djm Exp $ 36.\" $OpenBSD: sshd_config.5,v 1.175 2014/07/15 15:54:14 millert Exp $
37.Dd $Mdocdate: July 3 2014 $ 37.Dd $Mdocdate: July 15 2014 $
38.Dt SSHD_CONFIG 5 38.Dt SSHD_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -140,6 +140,26 @@ The default is
140Note that disabling TCP forwarding does not improve security unless 140Note that disabling TCP forwarding does not improve security unless
141users are also denied shell access, as they can always install their 141users are also denied shell access, as they can always install their
142own forwarders. 142own forwarders.
143.It Cm AllowStreamLocalForwarding
144Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted.
145The available options are
146.Dq yes
147or
148.Dq all
149to allow StreamLocal forwarding,
150.Dq no
151to prevent all StreamLocal forwarding,
152.Dq local
153to allow local (from the perspective of
154.Xr ssh 1 )
155forwarding only or
156.Dq remote
157to allow remote forwarding only.
158The default is
159.Dq yes .
160Note that disabling StreamLocal forwarding does not improve security unless
161users are also denied shell access, as they can always install their
162own forwarders.
143.It Cm AllowUsers 163.It Cm AllowUsers
144This keyword can be followed by a list of user name patterns, separated 164This keyword can be followed by a list of user name patterns, separated
145by spaces. 165by spaces.
@@ -1171,6 +1191,33 @@ This option applies to protocol version 1 only.
1171.It Cm ServerKeyBits 1191.It Cm ServerKeyBits
1172Defines the number of bits in the ephemeral protocol version 1 server key. 1192Defines the number of bits in the ephemeral protocol version 1 server key.
1173The minimum value is 512, and the default is 1024. 1193The minimum value is 512, and the default is 1024.
1194.It Cm StreamLocalBindMask
1195Sets the octal file creation mode mask
1196.Pq umask
1197used when creating a Unix-domain socket file for local or remote
1198port forwarding.
1199This option is only used for port forwarding to a Unix-domain socket file.
1200.Pp
1201The default value is 0177, which creates a Unix-domain socket file that is
1202readable and writable only by the owner.
1203Note that not all operating systems honor the file mode on Unix-domain
1204socket files.
1205.It Cm StreamLocalBindUnlink
1206Specifies whether to remove an existing Unix-domain socket file for local
1207or remote port forwarding before creating a new one.
1208If the socket file already exists and
1209.Cm StreamLocalBindUnlink
1210is not enabled,
1211.Nm sshd
1212will be unable to forward the port to the Unix-domain socket file.
1213This option is only used for port forwarding to a Unix-domain socket file.
1214.Pp
1215The argument must be
1216.Dq yes
1217or
1218.Dq no .
1219The default is
1220.Dq no .
1174.It Cm StrictModes 1221.It Cm StrictModes
1175Specifies whether 1222Specifies whether
1176.Xr sshd 8 1223.Xr sshd 8
diff --git a/sshlogin.c b/sshlogin.c
index e79ca9b47..7b951c844 100644
--- a/sshlogin.c
+++ b/sshlogin.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshlogin.c,v 1.28 2014/01/31 16:39:19 tedu Exp $ */ 1/* $OpenBSD: sshlogin.c,v 1.29 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -58,6 +58,7 @@
58#include "loginrec.h" 58#include "loginrec.h"
59#include "log.h" 59#include "log.h"
60#include "buffer.h" 60#include "buffer.h"
61#include "misc.h"
61#include "servconf.h" 62#include "servconf.h"
62 63
63extern Buffer loginmsg; 64extern Buffer loginmsg;