From 20adc8f2a99cd37b64a80ef63dfc5ba6627d4dfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Sun, 6 May 2018 12:24:45 +0000 Subject: [PATCH] Vendor import of OpenSSH 7.6p1. --- .gitignore | 28 + .skipped-commit-ids | 10 + ChangeLog | 5065 ++++++++--------- INSTALL | 2 +- LICENCE | 23 +- Makefile.in | 31 +- PROTOCOL | 6 +- PROTOCOL.agent | 585 +- PROTOCOL.certkeys | 21 +- README | 10 +- auth-options.c | 14 +- auth-options.h | 4 +- auth-pam.c | 47 +- auth.c | 165 +- auth.h | 81 +- auth2-chall.c | 37 +- auth2-gss.c | 77 +- auth2-hostbased.c | 111 +- auth2-kbdint.c | 6 +- auth2-none.c | 14 +- auth2-passwd.c | 32 +- auth2-pubkey.c | 580 +- auth2.c | 173 +- authfd.c | 174 +- authfd.h | 7 +- authfile.c | 115 +- bitmap.c | 9 +- bufbn.c | 42 +- buffer.h | 6 +- channels.c | 3891 ++++++------- channels.h | 226 +- cipher-3des1.c | 158 - cipher-bf1.c | 106 - cipher.c | 303 +- cipher.h | 29 +- clientloop.c | 853 +-- clientloop.h | 31 +- compat.c | 34 +- compat.h | 6 +- config.h.in | 42 +- configure | 335 +- configure.ac | 106 +- contrib/aix/README | 2 +- contrib/redhat/openssh.spec | 2 +- contrib/ssh-copy-id | 15 +- contrib/suse/openssh.spec | 2 +- deattack.c | 165 - deattack.h | 38 - defines.h | 29 + digest-libc.c | 12 +- digest-openssl.c | 3 +- digest.h | 13 +- dispatch.c | 21 +- dispatch.h | 14 +- dns.c | 2 +- dns.h | 2 +- gss-serv.c | 11 +- hostfile.c | 33 +- includes.h | 3 + kex.c | 81 +- kex.h | 9 +- kexc25519c.c | 7 +- kexc25519s.c | 5 +- kexdhc.c | 7 +- kexdhs.c | 7 +- kexecdhc.c | 7 +- kexecdhs.c | 7 +- kexgexc.c | 16 +- kexgexs.c | 12 +- key.c | 177 +- key.h | 36 +- krl.c | 4 +- log.c | 35 +- log.h | 4 +- mac.c | 9 +- md-sha256.c | 86 - misc.c | 473 +- misc.h | 22 +- moduli.0 | 2 +- monitor.c | 103 +- monitor_wrap.c | 31 +- monitor_wrap.h | 17 +- mux.c | 237 +- myproposal.h | 5 +- nchan.c | 385 +- opacket.c | 20 - opacket.h | 10 +- openbsd-compat/Makefile.in | 4 +- openbsd-compat/bsd-err.c | 6 + openbsd-compat/bsd-getpagesize.c | 23 + openbsd-compat/bsd-malloc.c | 55 + openbsd-compat/bsd-misc.c | 10 + openbsd-compat/bsd-misc.h | 4 + openbsd-compat/explicit_bzero.c | 4 + openbsd-compat/fmt_scaled.c | 18 +- openbsd-compat/freezero.c | 29 + openbsd-compat/openbsd-compat.h | 12 + openbsd-compat/port-tun.c | 95 +- openbsd-compat/port-tun.h | 5 +- openbsd-compat/recallocarray.c | 90 + packet.c | 800 +-- packet.h | 18 +- pathnames.h | 4 +- platform-misc.c | 35 + platform.c | 16 - readconf.c | 202 +- readconf.h | 16 +- regress/Makefile | 38 +- regress/agent-getpeereid.sh | 2 +- regress/agent-pkcs11.sh | 4 +- regress/agent.sh | 38 +- regress/authinfo.sh | 17 + regress/banner.sh | 8 +- regress/broken-pipe.sh | 17 +- regress/brokenkeys.sh | 6 +- regress/cert-file.sh | 119 +- regress/cert-hostkey.sh | 14 +- regress/cert-userkey.sh | 36 +- regress/cfgmatch.sh | 76 +- regress/cipher-speed.sh | 27 +- regress/connect-privsep.sh | 30 +- regress/connect.sh | 12 +- regress/dhgex.sh | 3 +- regress/dynamic-forward.sh | 20 +- regress/exit-status.sh | 34 +- regress/forcecommand.sh | 23 +- regress/forward-control.sh | 109 +- regress/forwarding.sh | 164 +- regress/host-expand.sh | 9 +- regress/hostkey-agent.sh | 4 +- regress/integrity.sh | 10 +- regress/key-options.sh | 52 +- regress/keygen-change.sh | 5 +- regress/keyscan.sh | 6 +- regress/keytype.sh | 15 +- regress/localcommand.sh | 14 +- regress/login-timeout.sh | 20 +- regress/misc/fuzz-harness/Makefile | 22 + regress/misc/fuzz-harness/README | 1 + regress/misc/fuzz-harness/pubkey_fuzz.cc | 18 + regress/misc/fuzz-harness/sig_fuzz.cc | 50 + regress/misc/kexfuzz/Makefile | 4 +- regress/misc/kexfuzz/kexfuzz.c | 4 +- regress/multiplex.sh | 6 +- regress/principals-command.sh | 18 +- regress/proto-mismatch.sh | 12 +- regress/proto-version.sh | 16 +- regress/proxy-connect.sh | 41 +- regress/putty-ciphers.sh | 4 +- regress/putty-transfer.sh | 45 +- regress/reconfigure.sh | 22 +- regress/reexec.sh | 32 +- regress/ssh-com.sh | 4 +- regress/stderr-after-eof.sh | 4 +- regress/stderr-data.sh | 14 +- regress/test-exec.sh | 37 +- regress/transfer.sh | 29 +- regress/try-ciphers.sh | 24 +- regress/unittests/Makefile.inc | 4 +- regress/unittests/hostkeys/mktestdata.sh | 16 +- regress/unittests/hostkeys/test_iterate.c | 249 +- .../unittests/hostkeys/testdata/known_hosts | 45 +- regress/unittests/sshkey/mktestdata.sh | 35 +- regress/unittests/sshkey/test_file.c | 51 +- regress/unittests/sshkey/test_fuzz.c | 45 +- regress/unittests/sshkey/test_sshkey.c | 22 +- regress/yes-head.sh | 18 +- rsa.c | 188 - rsa.h | 26 - sandbox-capsicum.c | 2 +- sandbox-seccomp-filter.c | 6 +- sandbox-solaris.c | 6 + scp.0 | 13 +- scp.1 | 19 +- scp.c | 42 +- servconf.c | 117 +- servconf.h | 15 +- serverloop.c | 133 +- serverloop.h | 6 +- session.c | 379 +- session.h | 18 +- sftp-client.c | 4 +- sftp-common.c | 25 +- sftp-server.0 | 2 +- sftp-server.c | 6 +- sftp.0 | 19 +- sftp.1 | 20 +- sftp.c | 58 +- ssh-add.0 | 32 +- ssh-add.1 | 21 +- ssh-add.c | 111 +- ssh-agent.0 | 2 +- ssh-agent.c | 742 +-- ssh-gss.h | 3 +- ssh-keygen.0 | 159 +- ssh-keygen.1 | 120 +- ssh-keygen.c | 292 +- ssh-keyscan.0 | 13 +- ssh-keyscan.1 | 14 +- ssh-keyscan.c | 129 +- ssh-keysign.0 | 2 +- ssh-pkcs11-client.c | 6 +- ssh-pkcs11-helper.0 | 2 +- ssh-pkcs11-helper.c | 14 +- ssh-pkcs11.c | 9 +- ssh-rsa.c | 45 +- ssh.0 | 81 +- ssh.1 | 92 +- ssh.c | 362 +- ssh.h | 9 +- ssh1.h | 91 - ssh_api.c | 3 +- ssh_config | 10 +- ssh_config.0 | 147 +- ssh_config.5 | 137 +- sshbuf-getput-basic.c | 4 +- sshbuf.c | 17 +- sshbuf.h | 3 +- sshconnect.c | 347 +- sshconnect.h | 18 +- sshconnect1.c | 774 --- sshconnect2.c | 141 +- sshd.0 | 24 +- sshd.8 | 26 +- sshd.c | 87 +- sshd_config.0 | 42 +- sshd_config.5 | 45 +- ssherr.c | 6 +- ssherr.h | 4 +- sshkey.c | 627 +- sshkey.h | 19 +- ttymodes.c | 123 +- ttymodes.h | 21 +- umac.c | 8 +- utf8.c | 7 +- version.h | 4 +- xmalloc.c | 14 +- xmalloc.h | 3 +- 238 files changed, 10538 insertions(+), 14624 deletions(-) create mode 100644 .gitignore delete mode 100644 cipher-3des1.c delete mode 100644 cipher-bf1.c delete mode 100644 deattack.c delete mode 100644 deattack.h delete mode 100644 md-sha256.c create mode 100644 openbsd-compat/bsd-getpagesize.c create mode 100644 openbsd-compat/bsd-malloc.c create mode 100644 openbsd-compat/freezero.c create mode 100644 openbsd-compat/recallocarray.c create mode 100644 platform-misc.c create mode 100644 regress/authinfo.sh create mode 100644 regress/misc/fuzz-harness/Makefile create mode 100644 regress/misc/fuzz-harness/README create mode 100644 regress/misc/fuzz-harness/pubkey_fuzz.cc create mode 100644 regress/misc/fuzz-harness/sig_fuzz.cc delete mode 100644 rsa.c delete mode 100644 rsa.h delete mode 100644 ssh1.h delete mode 100644 sshconnect1.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..650eb3c3c90c --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +Makefile +buildpkg.sh +config.h +config.h.in +config.status +configure +openbsd-compat/Makefile +openbsd-compat/regress/Makefile +openssh.xml +opensshd.init +survey.sh +**/*.0 +**/*.o +**/*.out +**/*.a +autom4te.cache/ +scp +sftp +sftp-server +ssh +ssh-add +ssh-agent +ssh-keygen +ssh-keyscan +ssh-keysign +ssh-pkcs11-helper +sshd +!regress/misc/fuzz-harness/Makefile diff --git a/.skipped-commit-ids b/.skipped-commit-ids index ee8241fb3bec..7c03c9db827a 100644 --- a/.skipped-commit-ids +++ b/.skipped-commit-ids @@ -11,3 +11,13 @@ f6ae971186ba68d066cd102e57d5b0b2c211a5ee systrace is dead. 96c5054e3e1f170c6276902d5bc65bb3b87a2603 remove DEBUGLIBS from Makefile 6da9a37f74aef9f9cc639004345ad893cad582d8 Update moduli file 77bcb50e47b68c7209c7f0a5a020d73761e5143b unset REGRESS_FAIL_EARLY +38c2133817cbcae75c88c63599ac54228f0fa384 Change COMPILER_VERSION tests +30c20180c87cbc99fa1020489fe7fd8245b6420c resync integrity.sh shell +1e6b51ddf767cbad0a4e63eb08026c127e654308 integrity.sh reliability +fe5b31f69a60d47171836911f144acff77810217 Makefile.inc bits +5781670c0578fe89663c9085ed3ba477cf7e7913 Delete sshconnect1.c +ea80f445e819719ccdcb237022cacfac990fdc5c Makefile.inc warning flags +b92c93266d8234d493857bb822260dacf4366157 moduli-gen.sh tweak +b25bf747544265b39af74fe0716dc8d9f5b63b95 Updated moduli +1bd41cba06a7752de4df304305a8153ebfb6b0ac rsa.[ch] already removed +e39b3902fe1d6c4a7ba6a3c58e072219f3c1e604 Makefile changes diff --git a/ChangeLog b/ChangeLog index 48f648d78fe3..e008ec9f383f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,2514 @@ +commit 66bf74a92131b7effe49fb0eefe5225151869dc5 +Author: djm@openbsd.org +Date: Mon Oct 2 19:33:20 2017 +0000 + + upstream commit + + Fix PermitOpen crash; spotted by benno@, ok dtucker@ deraadt@ + + Upstream-ID: c2cc84ffac070d2e1ff76182c70ca230a387983c + +commit d63b38160a59039708fd952adc75a0b3da141560 +Author: Damien Miller +Date: Sun Oct 1 10:32:25 2017 +1100 + + update URL again + + I spotted a typo in the draft so uploaded a new version... + +commit 6f64f596430cd3576c529f07acaaf2800aa17d58 +Author: Damien Miller +Date: Sun Oct 1 10:01:56 2017 +1100 + + sync release notes URL + +commit 35ff70a04dd71663a5ac1e73b90d16d270a06e0d +Author: Damien Miller +Date: Sun Oct 1 10:01:25 2017 +1100 + + sync contrib/ssh-copy-id with upstream + +commit 290843b8ede85f8b30bf29cd7dceb805c3ea5b66 +Author: Damien Miller +Date: Sun Oct 1 09:59:19 2017 +1100 + + update version in RPM spec files + +commit 4e4e0bb223c5be88d87d5798c75cc6b0d4fef31d +Author: Damien Miller +Date: Sun Oct 1 09:58:24 2017 +1100 + + update agent draft URL + +commit e4a798f001d2ecd8bf025c1d07658079f27cc604 +Author: djm@openbsd.org +Date: Sat Sep 30 22:26:33 2017 +0000 + + upstream commit + + openssh-7.6; ok deraadt@ + + Upstream-ID: a39c3a5b63a1baae109ae1ae4c7c34c2a59acde0 + +commit 5fa1407e16e7e5fda9769d53b626ce39d5588d4d +Author: jmc@openbsd.org +Date: Wed Sep 27 06:45:53 2017 +0000 + + upstream commit + + tweak EposeAuthinfo; diff from lars nooden + + tweaked by sthen; ok djm dtucker + + Upstream-ID: 8f2ea5d2065184363e8be7a0ba24d98a3b259748 + +commit bba69c246f0331f657fd6ec97724df99fc1ad174 +Author: Damien Miller +Date: Thu Sep 28 16:06:21 2017 -0700 + + don't fatal ./configure for LibreSSL + +commit 04dc070e8b4507d9d829f910b29be7e3b2414913 +Author: Damien Miller +Date: Thu Sep 28 14:54:34 2017 -0700 + + abort in configure when only openssl-1.1.x found + + We don't support openssl-1.1.x yet (see multiple threads on the + openssh-unix-dev@ mailing list for the reason), but previously + ./configure would accept it and the compilation would subsequently + fail. This makes ./configure display an explicit error message and + abort. + + ok dtucker@ + +commit 74c1c3660acf996d9dc329e819179418dc115f2c +Author: Darren Tucker +Date: Wed Sep 27 07:44:41 2017 +1000 + + Check for and handle calloc(p, 0) = NULL. + + On some platforms (AIX, maybe others) allocating zero bytes of memory + via the various *alloc functions returns NULL, which is permitted + by the standards. Autoconf has some macros for detecting this (with + the exception of calloc for some reason) so use these and if necessary + activate shims for them. ok djm@ + +commit 6a9481258a77b0b54b2a313d1761c87360c5f1f5 +Author: markus@openbsd.org +Date: Thu Sep 21 19:18:12 2017 +0000 + + upstream commit + + test reverse dynamic forwarding with SOCKS + + Upstream-Regress-ID: 95cf290470f7e5e2f691e4bc6ba19b91eced2f79 + +commit 1b9f321605733754df60fac8c1d3283c89b74455 +Author: Damien Miller +Date: Tue Sep 26 16:55:55 2017 +1000 + + sync missing changes in dynamic-forward.sh + +commit 44fc334c7a9ebdd08addb6d5fa005369897fddeb +Author: Darren Tucker +Date: Mon Sep 25 09:48:10 2017 +1000 + + Add minimal strsignal for platforms without it. + +commit 218e6f98df566fb9bd363f6aa47018cb65ede196 +Author: djm@openbsd.org +Date: Sun Sep 24 13:45:34 2017 +0000 + + upstream commit + + fix inverted test on channel open failure path that + "upgraded" a transient failure into a fatal error; reported by sthen and also + seen by benno@; ok sthen@ + + Upstream-ID: b58b3fbb79ba224599c6cd6b60c934fc46c68472 + +commit c704f641f7b8777497dc82e81f2ac89afec7e401 +Author: djm@openbsd.org +Date: Sun Sep 24 09:50:01 2017 +0000 + + upstream commit + + write the correct buffer when tunnel forwarding; doesn't + matter on OpenBSD (they are the same) but does matter on portable where we + use an output filter to translate os-specific tun/tap headers + + Upstream-ID: f1ca94eff48404827b12e1d12f6139ee99a72284 + +commit 55486f5cef117354f0c64f991895835077b7c7f7 +Author: djm@openbsd.org +Date: Sat Sep 23 22:04:07 2017 +0000 + + upstream commit + + fix tunnel forwarding problem introduced in refactor; + reported by stsp@ ok markus@ + + Upstream-ID: 81a731cdae1122c8522134095d1a8b60fa9dcd04 + +commit 609d7a66ce578abf259da2d5f6f68795c2bda731 +Author: markus@openbsd.org +Date: Thu Sep 21 19:16:53 2017 +0000 + + upstream commit + + Add 'reverse' dynamic forwarding which combines dynamic + forwarding (-D) with remote forwarding (-R) where the remote-forwarded port + expects SOCKS-requests. + + The SSH server code is unchanged and the parsing happens at the SSH + clients side. Thus the full SOCKS-request is sent over the forwarded + channel and the client parses c->output. Parsing happens in + channel_before_prepare_select(), _before_ the select bitmask is + computed in the pre[] handlers, but after network input processing + in the post[] handlers. + + help and ok djm@ + + Upstream-ID: aa25a6a3851064f34fe719e0bf15656ad5a64b89 + +commit 36945fa103176c00b39731e1fc1919a0d0808b81 +Author: dtucker@openbsd.org +Date: Wed Sep 20 05:19:00 2017 +0000 + + upstream commit + + Use strsignal in debug message instead of casting for the + benefit of portable where sig_atomic_t might not be int. "much nicer" + deraadt@ + + Upstream-ID: 2dac6c1e40511c700bd90664cd263ed2299dcf79 + +commit 3e8d185af326bf183b6f78597d5e3d2eeb2dc40e +Author: millert@openbsd.org +Date: Tue Sep 19 12:10:30 2017 +0000 + + upstream commit + + Use explicit_bzero() instead of bzero() before free() to + prevent the compiler from optimizing away the bzero() call. OK djm@ + + Upstream-ID: cdc6197e64c9684c7250e23d60863ee1b53cef1d + +commit 5b8da1f53854c0923ec6e927e86709e4d72737b6 +Author: djm@openbsd.org +Date: Tue Sep 19 04:24:22 2017 +0000 + + upstream commit + + fix use-after-free in ~^Z escape handler path, introduced + in channels.c refactor; spotted by millert@ "makes sense" deraadt@ + + Upstream-ID: 8fa2cdc65c23ad6420c1e59444b0c955b0589b22 + +commit a3839d8d2b89ff1a80cadd4dd654336710de2c9e +Author: dtucker@openbsd.org +Date: Mon Sep 18 12:03:24 2017 +0000 + + upstream commit + + Prevent type mismatch warning in debug on platforms where + sig_atomic_t != int. ok djm@ + + Upstream-ID: 306e2375eb0364a4c68e48f091739bea4f4892ed + +commit 30484e5e5f0b63d2c6ba32c6b85f06b6c6fa55fc +Author: dtucker@openbsd.org +Date: Mon Sep 18 09:41:52 2017 +0000 + + upstream commit + + Add braces missing after channels refactor. ok markus@ + + Upstream-ID: 72ab325c84e010680dbc88f226e2aa96b11a3980 + +commit b79569190b9b76dfacc6d996faa482f16e8fc026 +Author: Damien Miller +Date: Tue Sep 19 12:29:23 2017 +1000 + + add freezero(3) replacement + + ok dtucker@ + +commit 161af8f5ec0961b10cc032efb5cc1b44ced5a92e +Author: Damien Miller +Date: Tue Sep 19 10:18:56 2017 +1000 + + move FORTIFY_SOURCE into hardening options group + + It's still on by default, but now it's possible to turn it off using + --without-hardening. This is useful since it's known to cause problems + with some -fsanitize options. ok dtucker@ + +commit 09eacf856e0fe1a6e3fe597ec8032b7046292914 +Author: bluhm@openbsd.org +Date: Wed Sep 13 14:58:26 2017 +0000 + + upstream commit + + Print SKIPPED if sudo and doas configuration is missing. + Prevents that running the regression test with wrong environment is reported + as failure. Keep the fatal there to avoid interfering with other setups for + portable ssh. OK dtucker@ + + Upstream-Regress-ID: f0dc60023caef496ded341ac5aade2a606fa234e + +commit cdede10899892f25f1ccdccd7a3fe5e5ef0aa49a +Author: dtucker@openbsd.org +Date: Mon Aug 7 03:52:55 2017 +0000 + + upstream commit + + Remove obsolete privsep=no fallback test. + + Upstream-Regress-ID: 7d6e1baa1678ac6be50c2a1555662eb1047638df + +commit ec218c105daa9f5b192f7aa890fdb2d4fdc4e9d8 +Author: dtucker@openbsd.org +Date: Mon Aug 7 00:53:51 2017 +0000 + + upstream commit + + Remove non-privsep test since disabling privsep is now + deprecated. + + Upstream-Regress-ID: 77ad3f3d8d52e87f514a80f285c6c1229b108ce8 + +commit 239c57d5bc2253e27e3e6ad7ac52ec8c377ee24e +Author: dtucker@openbsd.org +Date: Fri Jul 28 10:32:08 2017 +0000 + + upstream commit + + Don't call fatal from stop_sshd since it calls cleanup + which calls stop_sshd which will probably fail in the same way. Instead, + just bail. Differentiate between sshd dying without cleanup and not shutting + down. + + Upstream-Regress-ID: f97315f538618b349e2b0bea02d6b0c9196c6bc4 + +commit aea59a0d9f120f2a87c7f494a0d9c51eaa79b8ba +Author: djm@openbsd.org +Date: Thu Sep 14 04:32:21 2017 +0000 + + upstream commit + + Revert commitid: gJtIN6rRTS3CHy9b. + + ------------- + identify the case where SSHFP records are missing but other DNS RR + types are present and display a more useful error message for this + case; patch by Thordur Bjornsson; bz#2501; ok dtucker@ + ------------- + + This caused unexpected failures when VerifyHostKeyDNS=yes, SSHFP results + are missing but the user already has the key in known_hosts + + Spotted by dtucker@ + + Upstream-ID: 97e31742fddaf72046f6ffef091ec0d823299920 + +commit 871f1e4374420b07550041b329627c474abc3010 +Author: Damien Miller +Date: Tue Sep 12 18:01:35 2017 +1000 + + adapt portable to channels API changes + +commit 4ec0bb9f9ad7b4eb0af110fa8eddf8fa199e46bb +Author: djm@openbsd.org +Date: Tue Sep 12 07:55:48 2017 +0000 + + upstream commit + + unused variable + + Upstream-ID: 2f9ba09f2708993d35eac5aa71df910dcc52bac1 + +commit 9145a73ce2ba30c82bbf91d7205bfd112529449f +Author: djm@openbsd.org +Date: Tue Sep 12 07:32:04 2017 +0000 + + upstream commit + + fix tun/tap forwarding case in previous + + Upstream-ID: 43ebe37a930320e24bca6900dccc39857840bc53 + +commit 9f53229c2ac97dbc6f5a03657de08a1150a9ac7e +Author: djm@openbsd.org +Date: Tue Sep 12 06:35:31 2017 +0000 + + upstream commit + + Make remote channel ID a u_int + + Previously we tracked the remote channel IDs in an int, but this is + strictly incorrect: the wire protocol uses uint32 and there is nothing + in-principle stopping a SSH implementation from sending, say, 0xffff0000. + + In practice everyone numbers their channels sequentially, so this has + never been a problem. + + ok markus@ + + Upstream-ID: b9f4cd3dc53155b4a5c995c0adba7da760d03e73 + +commit dbee4119b502e3f8b6cd3282c69c537fd01d8e16 +Author: djm@openbsd.org +Date: Tue Sep 12 06:32:07 2017 +0000 + + upstream commit + + refactor channels.c + + Move static state to a "struct ssh_channels" that is allocated at + runtime and tracked as a member of struct ssh. + + Explicitly pass "struct ssh" to all channels functions. + + Replace use of the legacy packet APIs in channels.c. + + Rework sshd_config PermitOpen handling: previously the configuration + parser would call directly into the channels layer. After the refactor + this is not possible, as the channels structures are allocated at + connection time and aren't available when the configuration is parsed. + The server config parser now tracks PermitOpen itself and explicitly + configures the channels code later. + + ok markus@ + + Upstream-ID: 11828f161656b965cc306576422613614bea2d8f + +commit abd59663df37a42152e37980113ccaa405b9a282 +Author: djm@openbsd.org +Date: Thu Sep 7 23:48:09 2017 +0000 + + upstream commit + + typo in comment + + Upstream-ID: a93b1e6f30f1f9b854b5b964b9fd092d0c422c47 + +commit 149a8cd24ce9dd47c36f571738681df5f31a326c +Author: jmc@openbsd.org +Date: Mon Sep 4 06:34:43 2017 +0000 + + upstream commit + + tweak previous; + + Upstream-ID: bb8cc40b61b15f6a13d81da465ac5bfc65cbfc4b + +commit ec9d22cc251cc5acfe7b2bcef9cc7a1fe0e949d8 +Author: Damien Miller +Date: Fri Sep 8 12:44:13 2017 +1000 + + Fuzzer harnesses for sig verify and pubkey parsing + + These are some basic clang libfuzzer harnesses for signature + verification and public key parsing. Some assembly (metaphorical) + required. + +commit de35c382894964a896a63ecd5607d3a3b93af75d +Author: Damien Miller +Date: Fri Sep 8 12:38:31 2017 +1000 + + Give configure ability to set CFLAGS/LDFLAGS later + + Some CFLAGS/LDFLAGS may disrupt the configure script's operation, + in particular santization and fuzzer options that break assumptions + about memory and file descriptor dispositions. + + This adds two flags to configure --with-cflags-after and + --with-ldflags-after that allow specifying additional compiler and + linker options that are added to the resultant Makefiles but not + used in the configure run itself. + + E.g. + + env CC=clang-3.9 ./configure \ + --with-cflags-after=-fsantize=address \ + --with-ldflags-after="-g -fsanitize=address" + +commit 22376d27a349f62c502fec3396dfe0fdcb2a40b7 +Author: djm@openbsd.org +Date: Sun Sep 3 23:33:13 2017 +0000 + + upstream commit + + Expand ssh_config's StrictModes option with two new + settings: + + StrictModes=accept-new will automatically accept hitherto-unseen keys + but will refuse connections for changed or invalid hostkeys. + + StrictModes=off is the same as StrictModes=no + + Motivation: + + StrictModes=no combines two behaviours for host key processing: + automatically learning new hostkeys and continuing to connect to hosts + with invalid/changed hostkeys. The latter behaviour is quite dangerous + since it removes most of the protections the SSH protocol is supposed to + provide. + + Quite a few users want to automatically learn hostkeys however, so + this makes that feature available with less danger. + + At some point in the future, StrictModes=no will change to be a synonym + for accept-new, with its current behaviour remaining available via + StrictModes=off. + + bz#2400, suggested by Michael Samuel; ok markus + + Upstream-ID: 0f55502bf75fc93a74fb9853264a8276b9680b64 + +commit ff3c42384033514e248ba5d7376aa033f4a2b99a +Author: jmc@openbsd.org +Date: Fri Sep 1 15:41:26 2017 +0000 + + upstream commit + + remove blank line; + + Upstream-ID: 2f46b51a0ddb3730020791719e94d3e418e9f423 + +commit b828605d51f57851316d7ba402b4ae06cf37c55d +Author: djm@openbsd.org +Date: Fri Sep 1 05:53:56 2017 +0000 + + upstream commit + + identify the case where SSHFP records are missing but + other DNS RR types are present and display a more useful error message for + this case; patch by Thordur Bjornsson; bz#2501; ok dtucker@ + + Upstream-ID: 8f7a5a8344f684823d8317a9708b63e75be2c244 + +commit 8042bad97e2789a50e8f742c3bcd665ebf0add32 +Author: djm@openbsd.org +Date: Fri Sep 1 05:50:48 2017 +0000 + + upstream commit + + document available AuthenticationMethods; bz#2453 ok + dtucker@ + + Upstream-ID: 2c70576f237bb699aff59889dbf2acba4276d3d0 + +commit 71e5a536ec815d542b199f2ae6d646c0db9f1b58 +Author: djm@openbsd.org +Date: Wed Aug 30 03:59:08 2017 +0000 + + upstream commit + + pass packet state down to some of the channels function + (more to come...); ok markus@ + + Upstream-ID: d8ce7a94f4059d7ac1e01fb0eb01de0c4b36c81b + +commit 6227fe5b362239c872b91bbdee4bf63cf85aebc5 +Author: jmc@openbsd.org +Date: Tue Aug 29 13:05:58 2017 +0000 + + upstream commit + + sort options; + + Upstream-ID: cf21d68cf54e81968bca629aaeddc87f0c684f3c + +commit 530591a5795a02d01c78877d58604723918aac87 +Author: dlg@openbsd.org +Date: Tue Aug 29 09:42:29 2017 +0000 + + upstream commit + + add a -q option to ssh-add to make it quiet on success. + + if you want to silence ssh-add without this you generally redirect + the output to /dev/null, but that can hide error output which you + should see. + + ok djm@ + + Upstream-ID: 2f31b9b13f99dcf587e9a8ba443458e6c0d8997c + +commit a54eb27dd64b5eca3ba94e15cec3535124bd5029 +Author: dtucker@openbsd.org +Date: Sun Aug 27 00:38:41 2017 +0000 + + upstream commit + + Increase the buffer sizes for user prompts to ensure that + they won't be truncated by snprintf. Based on patch from cjwatson at + debian.org via bz#2768, ok djm@ + + Upstream-ID: 6ffacf1abec8f40b469de5b94bfb29997d96af3e + +commit dd9d9b3381a4597b840d480b043823112039327e +Author: Darren Tucker +Date: Mon Aug 28 16:48:27 2017 +1000 + + Switch Capsicum header to sys/capsicum.h. + + FreeBSD's was renamed to in 2014 to + avoid future conflicts with POSIX capabilities (the last release that + didn't have it was 9.3) so switch to that. Patch from des at des.no. + +commit f5e917ab105af5dd6429348d9bc463e52b263f92 +Author: Darren Tucker +Date: Sun Aug 27 08:55:40 2017 +1000 + + Add missing includes for bsd-err.c. + + Patch from cjwatson at debian.org via bz#2767. + +commit 878e029797cfc9754771d6f6ea17f8c89e11d225 +Author: Damien Miller +Date: Fri Aug 25 13:25:01 2017 +1000 + + Split platform_sys_dir_uid into its own file + + platform.o is too heavy for libssh.a use; it calls into the server on + many platforms. Move just the function needed by misc.c into its own + file. + +commit 07949bfe9133234eddd01715592aa0dde67745f0 +Author: Damien Miller +Date: Wed Aug 23 20:13:18 2017 +1000 + + misc.c needs functions from platform.c now + +commit b074c3c3f820000a21953441cea7699c4b17d72f +Author: djm@openbsd.org +Date: Fri Aug 18 05:48:04 2017 +0000 + + upstream commit + + add a "quiet" flag to exited_cleanly() that supresses + errors about exit status (failure due to signal is still reported) + + Upstream-ID: db85c39c3aa08e6ff67fc1fb4ffa89f807a9d2f0 + +commit de4ae07f12dabf8815ecede54235fce5d22e3f63 +Author: djm@openbsd.org +Date: Fri Aug 18 05:36:45 2017 +0000 + + upstream commit + + Move several subprocess-related functions from various + locations to misc.c. Extend subprocess() to offer a little more control over + stdio disposition. + + feedback & ok dtucker@ + + Upstream-ID: 3573dd7109d13ef9bd3bed93a3deb170fbfce049 + +commit 643c2ad82910691b2240551ea8b14472f60b5078 +Author: djm@openbsd.org +Date: Sat Aug 12 06:46:01 2017 +0000 + + upstream commit + + make "--" before the hostname terminate command-line + option processing completely; previous behaviour would not prevent further + options appearing after the hostname (ssh has a supported options after the + hostname for >20 years, so that's too late to change). + + ok deraadt@ + + Upstream-ID: ef5ee50571b98ad94dcdf8282204e877ec88ad89 + +commit 0f3455356bc284d7c6f4d3c1614d31161bd5dcc2 +Author: djm@openbsd.org +Date: Sat Aug 12 06:42:52 2017 +0000 + + upstream commit + + Switch from aes256-cbc to aes256-ctr for encrypting + new-style private keys. The latter having the advantage of being supported + for no-OpenSSL builds; bz#2754 ok markus@ + + Upstream-ID: 54179a2afd28f93470471030567ac40431e56909 + +commit c4972d0a9bd6f898462906b4827e09b7caea2d9b +Author: djm@openbsd.org +Date: Fri Aug 11 04:47:12 2017 +0000 + + upstream commit + + refuse to a private keys when its corresponding .pub key + does not match. bz#2737 ok dtucker@ + + Upstream-ID: 54ff5e2db00037f9db8d61690f26ef8f16e0d913 + +commit 4b3ecbb663c919132dddb3758e17a23089413519 +Author: djm@openbsd.org +Date: Fri Aug 11 04:41:08 2017 +0000 + + upstream commit + + don't print verbose error message when ssh disconnects + under sftp; bz#2750; ok dtucker@ + + Upstream-ID: 6d83708aed77b933c47cf155a87dc753ec01f370 + +commit 42a8f8bc288ef8cac504c5c73f09ed610bc74a34 +Author: dtucker@openbsd.org +Date: Fri Aug 11 04:16:35 2017 +0000 + + upstream commit + + Tweak previous keepalive commit: if last_time + keepalive + <= now instead of just "<" so client_alive_check will fire if the select + happens to return on exact second of the timeout. ok djm@ + + Upstream-ID: e02756bd6038d11bb8522bfd75a4761c3a684fcc + +commit b60ff20051ef96dfb207b6bfa45c0ad6c34a542a +Author: dtucker@openbsd.org +Date: Fri Aug 11 03:58:36 2017 +0000 + + upstream commit + + Keep track of the last time we actually heard from the + client and use this to also schedule a client_alive_check(). Prevents + activity on a forwarded port from indefinitely preventing the select timeout + so that client_alive_check() will eventually (although not optimally) be + called. + + Analysis by willchan at google com via bz#2756, feedback & ok djm@ + + Upstream-ID: c08721e0bbda55c6d18e2760f3fe1b17fb71169e + +commit 94bc1e7ffba3cbdea8c7dcdab8376bf29283128f +Author: Damien Miller +Date: Fri Jul 28 14:50:59 2017 +1000 + + Expose list of completed auth methods to PAM + + bz#2408; ok dtucker@ + +commit c78e6eec78c88acf8d51db90ae05a3e39458603d +Author: Damien Miller +Date: Fri Jul 21 14:38:16 2017 +1000 + + fix problems in tunnel forwarding portability code + + This fixes a few problems in the tun forwarding code, mostly to do + with host/network byte order confusion. + + Based on a report and patch by stepe AT centaurus.uberspace.de; + bz#2735; ok dtucker@ + +commit 2985d4062ebf4204bbd373456a810d558698f9f5 +Author: dtucker@openbsd.org +Date: Tue Jul 25 09:22:25 2017 +0000 + + upstream commit + + Make WinSCP patterns for SSH_OLD_DHGEX more specific to + exclude WinSCP 5.10.x and up. bz#2748, from martin at winscp.net, ok djm@ + + Upstream-ID: 6fd7c32e99af3952db007aa180e73142ddbc741a + +commit 9f0e44e1a0439ff4646495d5735baa61138930a9 +Author: djm@openbsd.org +Date: Mon Jul 24 04:34:28 2017 +0000 + + upstream commit + + g/c unused variable; make a little more portable + + Upstream-ID: 3f5980481551cb823c6fb2858900f93fa9217dea + +commit 51676ec61491ec6d7cbd06082034e29b377b3bf6 +Author: djm@openbsd.org +Date: Sun Jul 23 23:37:02 2017 +0000 + + upstream commit + + Allow IPQoS=none in ssh/sshd to not set an explicit + ToS/DSCP value and just use the operating system default; ok dtucker@ + + Upstream-ID: 77906ff8c7b660b02ba7cb1e47b17d66f54f1f7e + +commit 6c1fbd5a50d8d2415f06c920dd3b1279b741072d +Author: Damien Miller +Date: Fri Jul 21 14:24:26 2017 +1000 + + mention libedit + +commit dc2bd308768386b02c7337120203ca477e67ba62 +Author: markus@openbsd.org +Date: Wed Jul 19 08:30:41 2017 +0000 + + upstream commit + + fix support for unknown key types; ok djm@ + + Upstream-ID: 53fb29394ed04d616d65b3748dee5aa06b07ab48 + +commit fd0e8fa5f89d21290b1fb5f9d110ca4f113d81d9 +Author: djm@openbsd.org +Date: Wed Jul 19 01:15:02 2017 +0000 + + upstream commit + + switch from select() to poll() for the ssh-agent + mainloop; ok markus + + Upstream-ID: 4a94888ee67b3fd948fd10693973beb12f802448 + +commit b1e72df2b813ecc15bd0152167bf4af5f91c36d3 +Author: dtucker@openbsd.org +Date: Fri Jul 14 03:18:21 2017 +0000 + + upstream commit + + Make ""Killed by signal 1" LogLevel verbose so it's not + shown at the default level. Prevents it from appearing during ssh -J and + equivalent ProxyCommand configs. bz#1906, bz#2744, feedback&ok markus@ + + Upstream-ID: debfaa7e859b272246c2f2633335d288d2e2ae28 + +commit 1f3d202770a08ee6752ed2a234b7ca6f180eb498 +Author: jmc@openbsd.org +Date: Thu Jul 13 19:16:33 2017 +0000 + + upstream commit + + man pages with pseudo synopses which list filenames end + up creating very ugly output in man -k; after some discussion with ingo, we + feel the simplest fix is to remove such SYNOPSIS sections: the info is hardly + helpful at page top, is contained already in FILES, and there are + sufficiently few that just zapping them is simple; + + ok schwarze, who also helpfully ran things through a build to check + output; + + Upstream-ID: 3e211b99457e2f4c925c5927d608e6f97431336c + +commit 7f13a4827fb28957161de4249bd6d71954f1f2ed +Author: espie@openbsd.org +Date: Mon Jul 10 14:09:59 2017 +0000 + + upstream commit + + zap redundant Makefile variables. okay djm@ + + Upstream-ID: e39b3902fe1d6c4a7ba6a3c58e072219f3c1e604 + +commit dc44dd3a9e2c9795394e6a7e1e71c929cbc70ce0 +Author: jmc@openbsd.org +Date: Sat Jul 8 18:32:54 2017 +0000 + + upstream commit + + slightly rework previous, to avoid an article issue; + + Upstream-ID: 15a315f0460ddd3d4e2ade1f16d6c640a8c41b30 + +commit 853edbe057a84ebd0024c8003e4da21bf2b469f7 +Author: djm@openbsd.org +Date: Fri Jul 7 03:53:12 2017 +0000 + + upstream commit + + When generating all hostkeys (ssh-keygen -A), clobber + existing keys if they exist but are zero length. zero-length keys could + previously be made if ssh-keygen failed part way through generating them, so + avoid that case too. bz#2561 reported by Krzysztof Cieplucha; ok dtucker@ + + Upstream-ID: f662201c28ab8e1f086b5d43c59cddab5ade4044 + +commit 43616876ba68a2ffaece6a6c792def4b039f2d6e +Author: djm@openbsd.org +Date: Sat Jul 1 22:55:44 2017 +0000 + + upstream commit + + actually remove these files + + Upstream-ID: 1bd41cba06a7752de4df304305a8153ebfb6b0ac + +commit 83fa3a044891887369ce8b487ce88d713a04df48 +Author: djm@openbsd.org +Date: Sat Jul 1 13:50:45 2017 +0000 + + upstream commit + + remove post-SSHv1 removal dead code from rsa.c and merge + the remaining bit that it still used into ssh-rsa.c; ok markus + + Upstream-ID: ac8a048d24dcd89594b0052ea5e3404b473bfa2f + +commit 738c73dca2c99ee78c531b4cbeefc2008fe438f0 +Author: Damien Miller +Date: Fri Jul 14 14:26:36 2017 +1000 + + make explicit_bzero/memset safe for sz=0 + +commit 8433d51e067e0829f5521c0c646b6fd3fe17e732 +Author: Tim Rice +Date: Tue Jul 11 18:47:56 2017 -0700 + + modified: configure.ac + UnixWare needs BROKEN_TCGETATTR_ICANON like Solaris + Analysis by Robbie Zhang + +commit ff3507aea9c7d30cd098e7801e156c68faff7cc7 +Author: Damien Miller +Date: Fri Jul 7 11:21:27 2017 +1000 + + typo + +commit d79bceb9311a9c137d268f5bc481705db4151810 +Author: dtucker@openbsd.org +Date: Fri Jun 30 04:17:23 2017 +0000 + + upstream commit + + Only call close once in confree(). ssh_packet_close will + close the FD so only explicitly close non-SSH channels. bz#2734, from + bagajjal at microsoft.com, ok djm@ + + Upstream-ID: a81ce0c8b023527167739fccf1732b154718ab02 + +commit 197dc9728f062e23ce374f44c95a2b5f9ffa4075 +Author: Darren Tucker +Date: Thu Jun 29 15:40:25 2017 +1000 + + Update link for my patches. + +commit a98339edbc1fc21342a390f345179a9c3031bef7 +Author: djm@openbsd.org +Date: Wed Jun 28 01:09:22 2017 +0000 + + upstream commit + + Allow ssh-keygen to use a key held in ssh-agent as a CA when + signing certificates. bz#2377 ok markus + + Upstream-ID: fb42e920b592edcbb5b50465739a867c09329c8f + +commit c9cdef35524bd59007e17d5bd2502dade69e2dfb +Author: djm@openbsd.org +Date: Sat Jun 24 06:35:24 2017 +0000 + + upstream commit + + regress test for ExposeAuthInfo + + Upstream-Regress-ID: 190e5b6866376f4061c411ab157ca4d4e7ae86fd + +commit f17ee61cad25d210edab69d04ed447ad55fe80c1 +Author: djm@openbsd.org +Date: Sat Jun 24 07:08:57 2017 +0000 + + upstream commit + + correct env var name + + Upstream-ID: 721e761c2b1d6a4dcf700179f16fd53a1dadb313 + +commit 40962198e3b132cecdb32e9350acd4294e6a1082 +Author: jmc@openbsd.org +Date: Sat Jun 24 06:57:04 2017 +0000 + + upstream commit + + spelling; + + Upstream-ID: 606f933c8e2d0be902ea663946bc15e3eee40b25 + +commit 33f86265d7e8a0e88d3a81745d746efbdd397370 +Author: djm@openbsd.org +Date: Sat Jun 24 06:38:11 2017 +0000 + + upstream commit + + don't pass pointer to struct sshcipher between privsep + processes, just redo the lookup in each using the already-passed cipher name. + bz#2704 based on patch from Brooks Davis; ok markus dtucker + + Upstream-ID: 2eab434c09bdf549dafd7da3e32a0d2d540adbe0 + +commit 8f574959272ac7fe9239c4f5d10fd913f8920ab0 +Author: djm@openbsd.org +Date: Sat Jun 24 06:34:38 2017 +0000 + + upstream commit + + refactor authentication logging + + optionally record successful auth methods and public credentials + used in a file accessible to user sessions + + feedback and ok markus@ + + Upstream-ID: 090b93036967015717b9a54fd0467875ae9d32fb + +commit e2004d4bb7eb01c663dd3a3e7eb224f1ccdc9bba +Author: jmc@openbsd.org +Date: Sat Jun 24 06:28:50 2017 +0000 + + upstream commit + + word fix; + + Upstream-ID: 8539bdaf2366603a34a9b2f034527ca13bb795c5 + +commit 4540428cd0adf039bcf5a8a27f2d5cdf09191513 +Author: djm@openbsd.org +Date: Sat Jun 24 05:37:44 2017 +0000 + + upstream commit + + switch sshconnect.c from (slightly abused) select() to + poll(); ok deraadt@ a while back + + Upstream-ID: efc1937fc591bbe70ac9e9542bb984f354c8c175 + +commit 6f8ca3b92540fa1a9b91670edc98d15448e3d765 +Author: djm@openbsd.org +Date: Sat Jun 24 05:35:05 2017 +0000 + + upstream commit + + use HostKeyAlias if specified instead of hostname for + matching host certificate principal names; bz#2728; ok dtucker@ + + Upstream-ID: dc2e11c83ae9201bbe74872a0c895ae9725536dd + +commit 8904ffce057b80a7472955f1ec00d7d5c250076c +Author: djm@openbsd.org +Date: Sat Jun 24 05:24:11 2017 +0000 + + upstream commit + + no need to call log_init to reinitialise logged PID in + child sessions, since we haven't called openlog() in log_init() since 1999; + ok markus@ + + Upstream-ID: 0906e4002af5d83d3d544df75e1187c932a3cf2e + +commit e238645d789cd7eb47541b66aea2a887ea122c9b +Author: mestre@openbsd.org +Date: Fri Jun 23 07:24:48 2017 +0000 + + upstream commit + + When using the escape sequence &~ the code path is + client_loop() -> client_simple_escape_filter() -> process_escapes() -> fork() + and the pledge for this path lacks the proc promise and therefore aborts the + process. The solution is to just add proc the promise to this specific + pledge. + + Reported by Gregoire Jadi gjadi ! omecha.info + Insight with tb@, OK jca@ + + Upstream-ID: 63c05e30c28209519f476023b65b0b1b0387a05b + +commit 5abbb31c4e7a6caa922cc1cbb14e87a77f9d19d3 +Author: dtucker@openbsd.org +Date: Fri Jun 23 03:30:42 2017 +0000 + + upstream commit + + Import regenerated moduli. + + Upstream-ID: b25bf747544265b39af74fe0716dc8d9f5b63b95 + +commit 849c5468b6d9b4365784c5dd88e3f1fb568ba38f +Author: dtucker@openbsd.org +Date: Fri Jun 23 03:25:53 2017 +0000 + + upstream commit + + Run the screen twice so we end up with more candidate + groups. ok djm@ + + Upstream-ID: b92c93266d8234d493857bb822260dacf4366157 + +commit 4626e39c7053c6486c1c8b708ec757e464623f5f +Author: dtucker@openbsd.org +Date: Wed Jun 14 00:31:38 2017 +0000 + + upstream commit + + Add user@host prefix to client's "Permisison denied" + messages, useful in particular when using "stacked" connections where it's + not clear which host is denying. bz#2720, ok djm@ markus@ + + Upstream-ID: de88e1e9dcb050c98e85377482d1287a9fe0d2be + +commit c948030d54911b2d3cddb96a7a8e9269e15d11cd +Author: djm@openbsd.org +Date: Tue Jun 13 12:13:59 2017 +0000 + + upstream commit + + Do not require that unknown EXT_INFO extension values not + contain \0 characters. This would cause fatal connection errors if an + implementation sent e.g. string-encoded sub-values inside a value. + + Reported by Denis Bider; ok markus@ + + Upstream-ID: 030e10fdc605563c040244c4b4f1d8ae75811a5c + +commit 6026f48dfca78b713e4a7f681ffa42a0afe0929e +Author: djm@openbsd.org +Date: Tue Jun 13 11:22:15 2017 +0000 + + upstream commit + + missing prototype. + + Upstream-ID: f443d2be9910fd2165a0667956d03343c46f66c9 + +commit bcd1485075aa72ba9418003f5cc27af2b049c51b +Author: Damien Miller +Date: Sat Jun 10 23:41:25 2017 +1000 + + portability for sftp globbed ls sort by mtime + + Include replacement timespeccmp() for systems that lack it. + Support time_t struct stat->st_mtime in addition to + timespec stat->st_mtim, as well as unsorted fallback. + +commit 072e172f1d302d2a2c6043ecbfb4004406717b96 +Author: djm@openbsd.org +Date: Sat Jun 10 06:36:46 2017 +0000 + + upstream commit + + print '?' instead of incorrect link count (that the + protocol doesn't provide) for remote listings. bz#2710 ok dtucker@ + + Upstream-ID: c611f98a66302cea452ef10f13fff8cf0385242e + +commit 72be5b2f8e7dc37235e8c4b8d0bc7b5ee1301505 +Author: djm@openbsd.org +Date: Sat Jun 10 06:33:34 2017 +0000 + + upstream commit + + implement sorting for globbed ls; bz#2649 ok dtucker@ + + Upstream-ID: ed3110f351cc9703411bf847ba864041fb7216a8 + +commit 5b2f34a74aa6a524cd57e856b23e1b7b25007721 +Author: djm@openbsd.org +Date: Fri Jun 9 06:47:13 2017 +0000 + + upstream commit + + return failure rather than fatal() for more cases during + mux negotiations. Causes the session to fall back to a non-mux connection if + they occur. bz#2707 ok dtucker@ + + Upstream-ID: d2a7892f464d434e1f615334a1c9d0cdb83b29ab + +commit 7f5637c4a67a49ef256cb4eedf14e8590ac30976 +Author: djm@openbsd.org +Date: Fri Jun 9 06:43:01 2017 +0000 + + upstream commit + + in description of public key authentication, mention that + the server will send debug messages to the client for some error conditions + after authentication has completed. bz#2709 ok dtucker + + Upstream-ID: 750127dbd58c5a2672c2d28bc35fe221fcc8d1dd + +commit 2076e4adb986512ce8c415dd194fd4e52136c4b4 +Author: djm@openbsd.org +Date: Fri Jun 9 06:40:24 2017 +0000 + + upstream commit + + better translate libcrypto errors by looking deeper in + the accursed error stack for codes that indicate the wrong passphrase was + supplied for a PEM key. bz#2699 ok dtucker@ + + Upstream-ID: 4da4286326d570f4f0489459bb71f6297e54b681 + +commit ad0531614cbe8ec424af3c0fa90c34a8e1ebee4c +Author: dtucker@openbsd.org +Date: Fri Jun 9 04:40:04 2017 +0000 + + upstream commit + + Add comments referring to the relevant RFC sections for + rekeying behaviour. + + Upstream-ID: 6fc8e82485757a27633f9175ad00468f49a07d40 + +commit ce9134260b9b1247e2385a1afed00c26112ba479 +Author: Damien Miller +Date: Fri Jun 9 14:43:47 2017 +1000 + + drop two more privileges in the Solaris sandbox + + Drop PRIV_DAX_ACCESS and PRIV_SYS_IB_INFO. + Patch from huieying.lee AT oracle.com via bz#2723 + +commit e0f609c8a2ab940374689ab8c854199c3c285a76 +Author: Darren Tucker +Date: Fri Jun 9 13:36:29 2017 +1000 + + Wrap stdint.h include in #ifdef. + +commit 1de5e47a85850526a4fdaf77185134046c050f75 +Author: djm@openbsd.org +Date: Wed Jun 7 01:48:15 2017 +0000 + + upstream commit + + unbreak after sshv1 purge + + Upstream-Regress-ID: 8ea01a92d5f571b9fba88c1463a4254a7552d51b + +commit 550c053168123fcc0791f9952abad684704b5760 +Author: dtucker@openbsd.org +Date: Tue Jun 6 09:12:17 2017 +0000 + + upstream commit + + Fix compression output stats broken in rev 1.201. Patch + originally by Russell Coker via Debian bug #797964 and Christoph Biedl. ok + djm@ + + Upstream-ID: 83a1903b95ec2e4ed100703debb4b4a313b01016 + +commit 55d06c6e72a9abf1c06a7ac2749ba733134a1f39 +Author: djm@openbsd.org +Date: Fri Jun 2 06:06:10 2017 +0000 + + upstream commit + + rationalise the long list of manual CDIAGFLAGS that we + add; most of these were redundant to -Wall -Wextra + + Upstream-ID: ea80f445e819719ccdcb237022cacfac990fdc5c + +commit 1527d9f61e6d50f6c2b4a3fa5b45829034b1b0b1 +Author: djm@openbsd.org +Date: Thu Jun 1 06:59:21 2017 +0000 + + upstream commit + + no need to bzero allocated space now that we use use + recallocarray; ok deraadt@ + + Upstream-ID: 53333c62ccf97de60b8cb570608c1ba5ca5803c8 + +commit cc812baf39b93d5355565da98648d8c31f955990 +Author: djm@openbsd.org +Date: Thu Jun 1 06:58:25 2017 +0000 + + upstream commit + + unconditionally zero init size of buffer; ok markus@ + deraadt@ + + Upstream-ID: 218963e846d8f26763ba25afe79294547b99da29 + +commit 65eb8fae0d7ba45ef4483a3cf0ae7fd0dbc7c226 +Author: Damien Miller +Date: Thu Jun 1 16:25:09 2017 +1000 + + avoid compiler warning + +commit 2d75d74272dc2a0521fce13cfe6388800c9a2406 +Author: djm@openbsd.org +Date: Thu Jun 1 06:16:43 2017 +0000 + + upstream commit + + some warnings spotted by clang; ok markus@ + + Upstream-ID: 24381d68ca249c5cee4388ceb0f383fa5b43991b + +commit 151c6e433a5f5af761c78de87d7b5d30a453cf5e +Author: Damien Miller +Date: Thu Jun 1 15:25:13 2017 +1000 + + add recallocarray replacement and dependency + + recallocarray() needs getpagesize() so add a tiny replacement for that. + +commit 01e6f78924da308447e71e9a32c8a6104ef4e888 +Author: Damien Miller +Date: Thu Jun 1 15:16:24 2017 +1000 + + add *.0 manpage droppings + +commit 4b2e2d3fd9dccff357e1e26ce9a5f2e103837a36 +Author: djm@openbsd.org +Date: Thu Jun 1 04:51:58 2017 +0000 + + upstream commit + + fix casts re constness + + Upstream-ID: e38f2bac162b37dbaf784d349c8327a6626fa266 + +commit 75b8af8de805c0694b37fcf80ce82783b2acc86f +Author: markus@openbsd.org +Date: Wed May 31 10:54:00 2017 +0000 + + upstream commit + + make sure we don't pass a NULL string to vfprintf + (triggered by the principals-command regress test); ok bluhm + + Upstream-ID: eb49854f274ab37a0b57056a6af379a0b7111990 + +commit 84008608c9ee944d9f72f5100f31ccff743b10f2 +Author: markus@openbsd.org +Date: Wed May 31 10:04:29 2017 +0000 + + upstream commit + + use SO_ZEROIZE for privsep communication (if available) + + Upstream-ID: abcbb6d2f8039fc4367a6a78096e5d5c39de4a62 + +commit 9e509d4ec97cb3d71696f1a2f1fdad254cbbce11 +Author: deraadt@openbsd.org +Date: Wed May 31 09:15:42 2017 +0000 + + upstream commit + + Switch to recallocarray() for a few operations. Both + growth and shrinkage are handled safely, and there also is no need for + preallocation dances. Future changes in this area will be less error prone. + Review and one bug found by markus + + Upstream-ID: 822d664d6a5a1d10eccb23acdd53578a679d5065 + +commit dc5dc45662773c0f7745c29cf77ae2d52723e55e +Author: deraadt@openbsd.org +Date: Wed May 31 08:58:52 2017 +0000 + + upstream commit + + These shutdown() SHUT_RDWR are not needed before close() + ok djm markus claudio + + Upstream-ID: 36f13ae4ba10f5618cb9347933101eb4a98dbcb5 + +commit 1e0cdf8efb745d0d1116e1aa22bdc99ee731695e +Author: markus@openbsd.org +Date: Wed May 31 08:09:45 2017 +0000 + + upstream commit + + clear session keys from memory; ok djm@ + + Upstream-ID: ecd178819868975affd5fd6637458b7c712b6a0f + +commit 92e9fe633130376a95dd533df6e5e6a578c1e6b8 +Author: markus@openbsd.org +Date: Wed May 31 07:00:13 2017 +0000 + + upstream commit + + remove now obsolete ctx from ssh_dispatch_run; ok djm@ + + Upstream-ID: 9870aabf7f4d71660c31fda91b942b19a8e68d29 + +commit 17ad5b346043c5bbc5befa864d0dbeb76be39390 +Author: markus@openbsd.org +Date: Wed May 31 05:34:14 2017 +0000 + + upstream commit + + use the ssh_dispatch_run_fatal variant + + Upstream-ID: 28c5b364e37c755d1b22652b8cd6735a05c625d8 + +commit 39896b777320a6574dd06707aebac5fb98e666da +Author: djm@openbsd.org +Date: Wed May 31 05:08:46 2017 +0000 + + upstream commit + + another ctx => ssh conversion (in GSSAPI code) + + Upstream-ID: 4d6574c3948075c60608d8e045af42fe5b5d8ae0 + +commit 6116bd4ed354a71a733c8fd0f0467ce612f12911 +Author: Damien Miller +Date: Wed May 31 14:56:07 2017 +1000 + + fix conversion of kexc25519s.c to struct ssh too + + git cvsimport missed this commit for some reason + +commit d40dbdc85b6fb2fd78485ba02225511b8cbf20d7 +Author: djm@openbsd.org +Date: Wed May 31 04:29:44 2017 +0000 + + upstream commit + + spell out that custom options/extensions should follow the + usual SSH naming rules, e.g. "extension@example.com" + + Upstream-ID: ab326666d2fad40769ec96b5a6de4015ffd97b8d + +commit 2a108277f976e8d0955c8b29d1dfde04dcbb3d5b +Author: djm@openbsd.org +Date: Wed May 31 04:17:12 2017 +0000 + + upstream commit + + one more void *ctx => struct ssh *ssh conversion + + Upstream-ID: d299d043471c10214cf52c03daa10f1c232759e2 + +commit c04e979503e97f52b750d3b98caa6fe004ab2ab9 +Author: djm@openbsd.org +Date: Wed May 31 00:43:04 2017 +0000 + + upstream commit + + fix possible OOB strlen() in SOCKS4A hostname parsing; + ok markus@ + + Upstream-ID: c67297cbeb0e5a19d81752aa18ec44d31270cd11 + +commit a3bb250c93bfe556838c46ed965066afce61cffa +Author: jmc@openbsd.org +Date: Tue May 30 19:38:17 2017 +0000 + + upstream commit + + tweak previous; + + Upstream-ID: 66987651046c42d142f7318c9695fb81a6d14031 + +commit 1112b534a6a7a07190e497e6bf86b0d5c5fb02dc +Author: bluhm@openbsd.org +Date: Tue May 30 18:58:37 2017 +0000 + + upstream commit + + Add RemoteCommand option to specify a command in the + ssh config file instead of giving it on the client's command line. This + command will be executed on the remote host. The feature allows to automate + tasks using ssh config. OK markus@ + + Upstream-ID: 5d982fc17adea373a9c68cae1021ce0a0904a5ee + +commit eb272ea4099fd6157846f15c129ac5727933aa69 +Author: markus@openbsd.org +Date: Tue May 30 14:29:59 2017 +0000 + + upstream commit + + switch auth2 to ssh_dispatch API; ok djm@ + + Upstream-ID: a752ca19e2782900dd83060b5c6344008106215f + +commit 5a146bbd4fdf5c571f9fb438e5210d28cead76d9 +Author: markus@openbsd.org +Date: Tue May 30 14:27:22 2017 +0000 + + upstream commit + + switch auth2-none.c to modern APIs; ok djm@ + + Upstream-ID: 07252b58e064d332214bcabbeae8e08c44b2001b + +commit 60306b2d2f029f91927c6aa7c8e08068519a0fa2 +Author: markus@openbsd.org +Date: Tue May 30 14:26:49 2017 +0000 + + upstream commit + + switch auth2-passwd.c to modern APIs; ok djm@ + + Upstream-ID: cba0a8b72b4f97adfb7e3b3fd2f8ba3159981fc7 + +commit eb76698b91338bd798c978d4db2d6af624d185e4 +Author: markus@openbsd.org +Date: Tue May 30 14:25:42 2017 +0000 + + upstream commit + + switch auth2-hostbased.c to modern APIs; ok djm@ + + Upstream-ID: 146af25c36daeeb83d5dbbb8ca52b5d25de88f4e + +commit 2ae666a8fc20b3b871b2f1b90ad65cc027336ccd +Author: markus@openbsd.org +Date: Tue May 30 14:23:52 2017 +0000 + + upstream commit + + protocol handlers all get struct ssh passed; ok djm@ + + Upstream-ID: 0ca9ea2a5d01a6d2ded94c5024456a930c5bfb5d + +commit 94583beb24a6c5fd19cedb9104ab2d2d5cd052b6 +Author: markus@openbsd.org +Date: Tue May 30 14:19:15 2017 +0000 + + upstream commit + + ssh: pass struct ssh to auth functions, too; ok djm@ + + Upstream-ID: d13c509cc782f8f19728fbea47ac7cf36f6e85dd + +commit 5f4082d886c6173b9e90b9768c9a38a3bfd92c2b +Author: markus@openbsd.org +Date: Tue May 30 14:18:15 2017 +0000 + + upstream commit + + sshd: pass struct ssh to auth functions; ok djm@ + + Upstream-ID: b00a80c3460884ebcdd14ef550154c761aebe488 + +commit 7da5df11ac788bc1133d8d598d298e33500524cc +Author: markus@openbsd.org +Date: Tue May 30 14:16:41 2017 +0000 + + upstream commit + + remove unused wrapper functions from key.[ch]; ok djm@ + + Upstream-ID: ea0f4016666a6817fc11f439dd4be06bab69707e + +commit ff7371afd08ac0bbd957d90451d4dcd0da087ef5 +Author: markus@openbsd.org +Date: Tue May 30 14:15:17 2017 +0000 + + upstream commit + + sshkey_new() might return NULL (pkcs#11 code only); ok + djm@ + + Upstream-ID: de9f2ad4a42c0b430caaa7d08dea7bac943075dd + +commit beb965bbc5a984fa69fb1e2b45ebe766ae09d1ef +Author: markus@openbsd.org +Date: Tue May 30 14:13:40 2017 +0000 + + upstream commit + + switch sshconnect.c to modern APIs; ok djm@ + + Upstream-ID: 27be17f84b950d5e139b7a9b281aa487187945ad + +commit 00ed75c92d1f95fe50032835106c368fa22f0f02 +Author: markus@openbsd.org +Date: Tue May 30 14:10:53 2017 +0000 + + upstream commit + + switch auth2-pubkey.c to modern APIs; with & ok djm@ + + Upstream-ID: 8f08d4316eb1b0c4ffe4a206c05cdd45ed1daf07 + +commit 54d90ace1d3535b44d92a8611952dc109a74a031 +Author: markus@openbsd.org +Date: Tue May 30 08:52:19 2017 +0000 + + upstream commit + + switch from Key typedef with struct sshkey; ok djm@ + + Upstream-ID: 3067d33e04efbe5131ce8f70668c47a58e5b7a1f + +commit c221219b1fbee47028dcaf66613f4f8d6b7640e9 +Author: markus@openbsd.org +Date: Tue May 30 08:49:58 2017 +0000 + + upstream commit + + remove ssh1 references; ok djm@ + + Upstream-ID: fc23b7578e7b0a8daaec72946d7f5e58ffff5a3d + +commit afbfa68fa18081ef05a9cd294958509a5d3cda8b +Author: markus@openbsd.org +Date: Tue May 30 08:49:32 2017 +0000 + + upstream commit + + revise sshkey_load_public(): remove ssh1 related + comments, remove extra open()/close() on keyfile, prevent leak of 'pub' if + 'keyp' is NULL, replace strlcpy+cat with asprintf; ok djm@ + + Upstream-ID: 6175e47cab5b4794dcd99c1175549a483ec673ca + +commit 813f55336a24fdfc45e7ed655fccc7d792e8f859 +Author: markus@openbsd.org +Date: Fri May 26 20:34:49 2017 +0000 + + upstream commit + + sshbuf_consume: reset empty buffer; ok djm@ + + Upstream-ID: 0d4583ba57f69e369d38bbd7843d85cac37fa821 + +commit 6cf711752cc2a7ffaad1fb4de18cae65715ed8bb +Author: markus@openbsd.org +Date: Fri May 26 19:35:50 2017 +0000 + + upstream commit + + remove SSH_CHANNEL_XXX_DRAINING (ssh1 only); ok djm@ + + Upstream-ID: e2e225b6ac67b84dd024f38819afff2554fafe42 + +commit 364f0d5edea27767fb0f915ea7fc61aded88d3e8 +Author: markus@openbsd.org +Date: Fri May 26 19:34:12 2017 +0000 + + upstream commit + + remove channel_input_close_confirmation (ssh1 only); ok + djm@ + + Upstream-ID: 8e7c8c38f322d255bb0294a5c0ebef53fdf576f1 + +commit 8ba0fd40082751dbbc23a830433488bbfb1abdca +Author: djm@openbsd.org +Date: Fri May 26 01:40:07 2017 +0000 + + upstream commit + + fix references to obsolete v00 cert format; spotted by + Jakub Jelen + + Upstream-ID: 7600ce193ab8fd19451acfe24fc2eb39d46b2c4f + +commit dcc714c65cfb81eb6903095b4590719e8690f3da +Author: Mike Frysinger +Date: Wed May 24 23:21:19 2017 -0400 + + configure: actually set cache vars when cross-compiling + + The cross-compiling fallback message says it's assuming the test + passed, but it didn't actually set the cache var which causes + later tests to fail. + +commit 947a3e829a5b8832a4768fd764283709a4ca7955 +Author: djm@openbsd.org +Date: Sat May 20 02:35:47 2017 +0000 + + upstream commit + + there's no reason to artificially limit the key path + here, just check that it fits PATH_MAX; spotted by Matthew Patton + + Upstream-ID: 858addaf2009c9cf04d80164a41b2088edb30b58 + +commit 773224802d7cb250bb8b461546fcce10567b4b2e +Author: djm@openbsd.org +Date: Fri May 19 21:07:17 2017 +0000 + + upstream commit + + Now that we no longer support SSHv1, replace the contents + of this file with a pointer to + https://tools.ietf.org/html/draft-miller-ssh-agent-00 It's better edited, + doesn't need to document stuff we no longer implement and does document stuff + that we do implement (RSA SHA256/512 signature flags) + + Upstream-ID: da8cdc46bbcc266efabd565ddddd0d8e556f846e + +commit 54cd41a4663fad66406dd3c8fe0e4760ccd8a899 +Author: djm@openbsd.org +Date: Wed May 17 01:24:17 2017 +0000 + + upstream commit + + allow LogLevel in sshd_config Match blocks; ok dtucker + bz#2717 + + Upstream-ID: 662e303be63148f47db1aa78ab81c5c2e732baa8 + +commit 277abcda3f1b08d2376686f0ef20320160d4c8ab +Author: djm@openbsd.org +Date: Tue May 16 16:56:15 2017 +0000 + + upstream commit + + remove duplicate check; spotted by Jakub Jelen + + Upstream-ID: 30c2996c1767616a8fdc49d4cee088efac69c3b0 + +commit adb47ce839c977fa197e770c1be8f852508d65aa +Author: djm@openbsd.org +Date: Tue May 16 16:54:05 2017 +0000 + + upstream commit + + mention that Ed25519 keys are valid as CA keys; spotted + by Jakub Jelen + + Upstream-ID: d3f6db58b30418cb1c3058211b893a1ffed3dfd4 + +commit 6bdf70f01e700348bb4d8c064c31a0ab90896df6 +Author: Damien Miller +Date: Tue May 9 14:35:03 2017 +1000 + + clean up regress files and add a .gitignore + +commit 7bdb2eeb1d3c26acdc409bd94532eefa252e440b +Author: djm@openbsd.org +Date: Mon May 8 22:57:38 2017 +0000 + + upstream commit + + remove hmac-ripemd160; ok dtucker + + Upstream-ID: 896e737ea0bad6e23327d1c127e02d5e9e9c654d + +commit 5f02bb1f99f70bb422be8a5c2b77ef853f1db554 +Author: djm@openbsd.org +Date: Mon May 8 06:11:06 2017 +0000 + + upstream commit + + make requesting bad ECDSA bits yield the same error + (SSH_ERR_KEY_LENGTH) as the same mistake for RSA/DSA + + Upstream-ID: bf40d3fee567c271e33f05ef8e4e0fa0b6f0ece6 + +commit d757a4b633e8874629a1442c7c2e7b1b55d28c19 +Author: djm@openbsd.org +Date: Mon May 8 06:08:42 2017 +0000 + + upstream commit + + fix for new SSH_ERR_KEY_LENGTH error value + + Upstream-Regress-ID: c38a6e6174d4c3feca3518df150d4fbae0dca8dc + +commit 2e58a69508ac49c02d1bb6057300fa6a76db1045 +Author: djm@openbsd.org +Date: Mon May 8 06:03:39 2017 +0000 + + upstream commit + + helps if I commit the correct version of the file. fix + missing return statement. + + Upstream-ID: c86394a3beeb1ec6611e659bfa830254f325546c + +commit effaf526bfa57c0ac9056ca236becf52385ce8af +Author: djm@openbsd.org +Date: Mon May 8 01:52:49 2017 +0000 + + upstream commit + + remove arcfour, blowfish and CAST here too + + Upstream-Regress-ID: c613b3bcbef75df1fe84ca4dc2d3ef253dc5e920 + +commit 7461a5bc571696273252df28a1f1578968cae506 +Author: djm@openbsd.org +Date: Mon May 8 00:21:36 2017 +0000 + + upstream commit + + I was too aggressive with the scalpel in the last commit; + unbreak sshd, spotted quickly by naddy@ + + Upstream-ID: fb7e75d2b2c7e6ca57dee00ca645e322dd49adbf + +commit bd636f40911094a39c2920bf87d2ec340533c152 +Author: djm@openbsd.org +Date: Sun May 7 23:15:59 2017 +0000 + + upstream commit + + Refuse RSA keys <1024 bits in length. Improve reporting + for keys that do not meet this requirement. ok markus@ + + Upstream-ID: b385e2a7b13b1484792ee681daaf79e1e203df6c + +commit 70c1218fc45757a030285051eb4d209403f54785 +Author: djm@openbsd.org +Date: Sun May 7 23:13:42 2017 +0000 + + upstream commit + + Don't offer CBC ciphers by default in the client. ok + markus@ + + Upstream-ID: 94c9ce8d0d1a085052e11c7f3307950fdc0901ef + +commit acaf34fd823235d549c633c0146ee03ac5956e82 +Author: djm@openbsd.org +Date: Sun May 7 23:12:57 2017 +0000 + + upstream commit + + As promised in last release announcement: remove + support for Blowfish, RC4 and CAST ciphers. ok markus@ deraadt@ + + Upstream-ID: 21f8facdba3fd8da248df6417000867cec6ba222 + +commit 3e371bd2124427403971db853fb2e36ce789b6fd +Author: naddy@openbsd.org +Date: Fri May 5 10:42:49 2017 +0000 + + upstream commit + + more simplification and removal of SSHv1-related code; + ok djm@ + + Upstream-ID: d2f041aa0b79c0ebd98c68a01e5a0bfab2cf3b55 + +commit 2e9c324b3a7f15c092d118c2ac9490939f6228fd +Author: naddy@openbsd.org +Date: Fri May 5 10:41:58 2017 +0000 + + upstream commit + + remove superfluous protocol 2 mentions; ok jmc@ + + Upstream-ID: 0aaf7567c9f2e50fac5906b6a500a39c33c4664d + +commit 744bde79c3361e2153cb395a2ecdcee6c713585d +Author: djm@openbsd.org +Date: Thu May 4 06:10:57 2017 +0000 + + upstream commit + + since a couple of people have asked, leave a comment + explaining why we retain SSH v.1 support in the "delete all keys from agent" + path. + + Upstream-ID: 4b42dcfa339813c15fe9248a2c1b7ed41c21bbb4 + +commit 0c378ff6d98d80bc465a4a6a787670fb9cc701ee +Author: djm@openbsd.org +Date: Thu May 4 01:33:21 2017 +0000 + + upstream commit + + another tentacle: cipher_set_key_string() was only ever + used for SSHv1 + + Upstream-ID: 7fd31eb6c48946f7e7cc12af0699fe8eb637e94a + +commit 9a82e24b986e3e0dc70849dbb2c19aa6c707b37f +Author: naddy@openbsd.org +Date: Wed May 3 21:49:18 2017 +0000 + + upstream commit + + restore mistakenly deleted description of the + ConnectionAttempts option ok markus@ + + Upstream-ID: 943002b1b7c470caea3253ba7b7348c359de0348 + +commit 768405fddf64ff83aa6ef701ebb3c1f82d98a2f3 +Author: naddy@openbsd.org +Date: Wed May 3 21:08:09 2017 +0000 + + upstream commit + + remove miscellaneous SSH1 leftovers; ok markus@ + + Upstream-ID: af23696022ae4d45a1abc2fb8b490d8d9dd63b7c + +commit 1a1b24f8229bf7a21f89df21987433283265527a +Author: jmc@openbsd.org +Date: Wed May 3 10:01:44 2017 +0000 + + upstream commit + + more protocol 1 bits removed; ok djm + + Upstream-ID: b5b977eaf756915acb56aef3604a650e27f7c2b9 + +commit 2b6f799e9b230cf13a7eefc05ecead7d8569d6b5 +Author: jmc@openbsd.org +Date: Wed May 3 06:32:02 2017 +0000 + + upstream commit + + more protocol 1 stuff to go; ok djm + + Upstream-ID: 307a30441d2edda480fd1661d998d36665671e47 + +commit f10c0d32cde2084d2a0b19bc47d80cb93e85a093 +Author: jmc@openbsd.org +Date: Tue May 2 17:04:09 2017 +0000 + + upstream commit + + rsa1 is no longer valid; + + Upstream-ID: 9953d09ed9841c44b7dcf7019fa874783a709d89 + +commit 42b690b4fd0faef78c4d68225948b6e5c46c5163 +Author: jmc@openbsd.org +Date: Tue May 2 14:06:37 2017 +0000 + + upstream commit + + add PubKeyAcceptedKeyTypes to the -o list: scp(1) has + it, so i guess this should too; + + Upstream-ID: 7fab32e869ca5831d09ab0c40d210b461d527a2c + +commit d852603214defd93e054de2877b20cc79c19d0c6 +Author: jmc@openbsd.org +Date: Tue May 2 13:44:51 2017 +0000 + + upstream commit + + remove now obsolete protocol1 options from the -o + lists; + + Upstream-ID: 828e478a440bc5f9947672c392420510a362b3dd + +commit 8b60ce8d8111e604c711c4cdd9579ffe0edced74 +Author: jmc@openbsd.org +Date: Tue May 2 09:05:58 2017 +0000 + + upstream commit + + more -O shuffle; ok djm + + Upstream-ID: c239991a3a025cdbb030b73e990188dd9bfbeceb + +commit 3575f0b12afe6b561681582fd3c34067d1196231 +Author: djm@openbsd.org +Date: Tue May 2 08:54:19 2017 +0000 + + upstream commit + + remove -1 / -2 options; pointed out by jmc@ + + Upstream-ID: 65d2a816000741a95df1c7cfdb5fa8469fcc7daa + +commit 4f1ca823bad12e4f9614895eefe0d0073b84a28f +Author: jmc@openbsd.org +Date: Tue May 2 08:06:33 2017 +0000 + + upstream commit + + remove options -12 from usage(); + + Upstream-ID: db7ceef25132e63b50ed05289bf447fece1d1270 + +commit 6b84897f7fd39956b849eac7810319d8a9958568 +Author: jmc@openbsd.org +Date: Tue May 2 07:13:31 2017 +0000 + + upstream commit + + tidy up -O somewhat; ok djm + + Upstream-ID: 804405f716bf7ef15c1f36ab48581ca16aeb4d52 + +commit d1c6b7fdbdfe4a7a37ecd48a97f0796b061c2868 +Author: djm@openbsd.org +Date: Mon May 1 22:09:48 2017 +0000 + + upstream commit + + when freeing a bitmap, zero all it bytes; spotted by Ilya + Kaliman + + Upstream-ID: 834ac024f2c82389d6ea6b1c7d6701b3836e28e4 + +commit 0f163983016c2988a92e039d18a7569f9ea8e071 +Author: djm@openbsd.org +Date: Mon May 1 14:08:26 2017 +0000 + + upstream commit + + this one I did forget to "cvs rm" + + Upstream-ID: 5781670c0578fe89663c9085ed3ba477cf7e7913 + +commit 21ed00a8e26fe8a772bcca782175fafc2b0890ed +Author: djm@openbsd.org +Date: Mon May 1 09:27:45 2017 +0000 + + upstream commit + + don't know why cvs didn't exterminate these the first + time around, I use rm -f and everuthing... + + pointed out by sobrado@ + + Upstream-ID: a6c44a0c2885330d322ee01fcfd7f6f209b1e15d + +commit d29ba6f45086703fdcb894532848ada3427dfde6 +Author: Darren Tucker +Date: Mon May 1 13:53:07 2017 +1000 + + Define INT32_MAX and INT64_MAX if needed. + +commit 329037e389f02ec95c8e16bf93ffede94d3d44ce +Author: Darren Tucker +Date: Mon May 1 13:19:41 2017 +1000 + + Wrap stdint.h in HAVE_STDINT_H + +commit f382362e8dfb6b277f16779ab1936399d7f2af78 +Author: djm@openbsd.org +Date: Mon May 1 02:27:11 2017 +0000 + + upstream commit + + remove unused variable + + Upstream-ID: 66011f00819d0e71b14700449a98414033284516 + +commit dd369320d2435b630a5974ab270d686dcd92d024 +Author: djm@openbsd.org +Date: Sun Apr 30 23:34:55 2017 +0000 + + upstream commit + + eliminate explicit specification of protocol in tests and + loops over protocol. We only support SSHv2 now. + + Upstream-Regress-ID: 0082838a9b8a382b7ee9cbf0c1b9db727784fadd + +commit 557f921aad004be15805e09fd9572969eb3d9321 +Author: djm@openbsd.org +Date: Sun Apr 30 23:33:48 2017 +0000 + + upstream commit + + remove SSHv1 support from unit tests + + Upstream-Regress-ID: 395ca2aa48f1f7d23eefff6cb849ea733ca8bbfe + +commit e77e1562716fb3da413e4c2397811017b762f5e3 +Author: djm@openbsd.org +Date: Mon May 1 00:03:18 2017 +0000 + + upstream commit + + fixup setting ciphercontext->plaintext (lost in SSHv1 purge), + though it isn't really used for much anymore. + + Upstream-ID: 859b8bce84ff4865b32097db5430349d04b9b747 + +commit f7849e6c83a4e0f602dea6c834a24091c622d68e +Author: Damien Miller +Date: Mon May 1 09:55:56 2017 +1000 + + remove configure --with-ssh1 + +commit f4a6a88ddb6dba6d2f7bfb9e2c9879fcc9633043 +Author: djm@openbsd.org +Date: Sun Apr 30 23:29:10 2017 +0000 + + upstream commit + + flense SSHv1 support from ssh-agent, considerably + simplifying it + + ok markus + + Upstream-ID: 71d772cdcefcb29f76e01252e8361e6fc2dfc365 + +commit 930e8d2827853bc2e196c20c3e000263cc87fb75 +Author: djm@openbsd.org +Date: Sun Apr 30 23:28:41 2017 +0000 + + upstream commit + + obliterate ssh1.h and some dead code that used it + + ok markus@ + + Upstream-ID: 1ca9159a9fb95618f9d51e069ac8e1131a087343 + +commit a3710d5d529a34b8f56aa62db798c70e85d576a0 +Author: djm@openbsd.org +Date: Sun Apr 30 23:28:12 2017 +0000 + + upstream commit + + exterminate the -1 flag from scp + + ok markus@ + + Upstream-ID: 26d247f7065da15056b209cef5f594ff591b89db + +commit aebd0abfaa8a41e75d50f9f7934267b0a2d9acb4 +Author: djm@openbsd.org +Date: Sun Apr 30 23:26:54 2017 +0000 + + upstream commit + + purge the last traces of SSHv1 from the TTY modes + handling code + + ok markus + + Upstream-ID: 963a19f1e06577377c38a3b7ce468f121b966195 + +commit dfa641f758d4b8b2608ab1b00abaf88df0a8e36a +Author: djm@openbsd.org +Date: Sun Apr 30 23:26:16 2017 +0000 + + upstream commit + + remove the (in)famous SSHv1 CRC compensation attack + detector. + + Despite your cameo in The Matrix movies, you will not be missed. + + ok markus + + Upstream-ID: 44261fce51a56d93cdb2af7b6e184be629f667e0 + +commit e5d3bd36ef67d82092861f39b5bf422cb12b31a6 +Author: djm@openbsd.org +Date: Sun Apr 30 23:25:03 2017 +0000 + + upstream commit + + undo some local debugging stuff that I committed by + accident + + Upstream-ID: fe5b31f69a60d47171836911f144acff77810217 + +commit 3d6d09f2e90f4ad650ebda6520bf2da446f37f14 +Author: djm@openbsd.org +Date: Sun Apr 30 23:23:54 2017 +0000 + + upstream commit + + remove SSHv1 support from packet and buffer APIs + + ok markus@ + + Upstream-ID: bfc290053d40b806ecac46317d300677d80e1dc9 + +commit 05164358577c82de18ed7373196bc7dbd8a3f79c +Author: djm@openbsd.org +Date: Sun Apr 30 23:21:54 2017 +0000 + + upstream commit + + remove SSHv1-related buffers from client code + + Upstream-ID: dca5d01108f891861ceaf7ba1c0f2eb274e0c7dd + +commit 873d3e7d9a4707d0934fb4c4299354418f91b541 +Author: djm@openbsd.org +Date: Sun Apr 30 23:18:44 2017 +0000 + + upstream commit + + remove KEY_RSA1 + + ok markus@ + + Upstream-ID: 7408517b077c892a86b581e19f82a163069bf133 + +commit 788ac799a6efa40517f2ac0d895a610394298ffc +Author: djm@openbsd.org +Date: Sun Apr 30 23:18:22 2017 +0000 + + upstream commit + + remove SSHv1 configuration options and man pages bits + + ok markus@ + + Upstream-ID: 84638c23546c056727b7a7d653c72574e0f19424 + +commit e6882463a8ae0594aacb6d6575a6318a41973d84 +Author: djm@openbsd.org +Date: Sun Apr 30 23:17:37 2017 +0000 + + upstream commit + + remove SSH1 make flag and associated files ok markus@ + + Upstream-ID: ba9feacc5787337c413db7cf26ea3d53f854cfef + +commit cdccebdf85204bf7542b7fcc1aa2ea3f36661833 +Author: djm@openbsd.org +Date: Sun Apr 30 23:15:04 2017 +0000 + + upstream commit + + remove SSHv1 ciphers; ok markus@ + + Upstream-ID: e5ebc5e540d7f23a8c1266db1839794d4d177890 + +commit 97f4d3083b036ce3e68d6346a6140a22123d5864 +Author: djm@openbsd.org +Date: Sun Apr 30 23:13:25 2017 +0000 + + upstream commit + + remove compat20/compat13/compat15 variables + + ok markus@ + + Upstream-ID: 43802c035ceb3fef6c50c400e4ecabf12354691c + +commit 99f95ba82673d33215dce17bfa1512b57f54ec09 +Author: djm@openbsd.org +Date: Sun Apr 30 23:11:45 2017 +0000 + + upstream commit + + remove options.protocol and client Protocol + configuration knob + + ok markus@ + + Upstream-ID: 5a967f5d06e2d004b0235457b6de3a9a314e9366 + +commit 56912dea6ef63dae4eb1194e5d88973a7c6c5740 +Author: djm@openbsd.org +Date: Sun Apr 30 23:10:43 2017 +0000 + + upstream commit + + unifdef WITH_SSH1 ok markus@ + + Upstream-ID: 9716e62a883ef8826c57f4d33b4a81a9cc7755c7 + +commit d4084cd230f7319056559b00db8b99296dad49d5 +Author: jmc@openbsd.org +Date: Sat Apr 29 06:06:01 2017 +0000 + + upstream commit + + tweak previous; + + Upstream-ID: a3abc6857455299aa42a046d232b7984568bceb9 + +commit 249516e428e8461b46340a5df5d5ed1fbad2ccce +Author: djm@openbsd.org +Date: Sat Apr 29 04:12:25 2017 +0000 + + upstream commit + + allow ssh-keygen to include arbitrary string or flag + certificate extensions and critical options. ok markus@ dtucker@ + + Upstream-ID: 2cf28dd6c5489eb9fc136e0b667ac3ea10241646 + +commit 47a287bb6ac936c26b4f3ae63279c02902ded3b9 +Author: jmc@openbsd.org +Date: Fri Apr 28 06:15:03 2017 +0000 + + upstream commit + + sort; + + Upstream-ID: 7e6b56e52b039cf44d0418e9de9aca20a2d2d15a + +commit 36465a76a79ad5040800711b41cf5f32249d5120 +Author: Darren Tucker +Date: Fri Apr 28 14:44:28 2017 +1000 + + Typo. + + Upstream-Regress-ID: 1e6b51ddf767cbad0a4e63eb08026c127e654308 + +commit 9d18cb7bdeb00b20205fd13d412aae8c0e0457ed +Author: Darren Tucker +Date: Fri Apr 28 14:41:17 2017 +1000 + + Add 2 regress commits I applied by hand. + + Upstream-Regress-ID: 30c20180c87cbc99fa1020489fe7fd8245b6420c + Upstream-Regress-ID: 1e6b51ddf767cbad0a4e63eb08026c127e654308 + +commit 9504ea6b27f9f0ece64e88582ebb9235e664a100 +Author: Darren Tucker +Date: Fri Apr 28 14:33:43 2017 +1000 + + Merge integrity.sh rev 1.22. + + Merge missing bits from Colin Watson's patch in bz#2658 which make integrity + tests more robust against timeouts. ok djm@ + +commit 06ec837a34542627e2183a412d6a9d2236f22140 +Author: Darren Tucker +Date: Fri Apr 28 14:30:03 2017 +1000 + + Id sync for integrity.sh rev 1.21 which pulls in some shell portability fixes + +commit e0194b471efe7d3daedc9cc66686cb1ab69d3be8 +Author: jsg@openbsd.org +Date: Mon Apr 17 11:02:31 2017 +0000 + + upstream commit + + Change COMPILER_VERSION tests which limited additional + warnings to gcc4 to instead skip them on gcc3 as clang can handle + -Wpointer-sign and -Wold-style-definition. + + Upstream-Regress-ID: e48d7dc13e48d9334b8195ef884dfbc51316012f + +commit 6830be90e71f46bcd182a9202b151eaf2b299434 +Author: djm@openbsd.org +Date: Fri Apr 28 03:24:53 2017 +0000 + + upstream commit + + include key fingerprint in "Offering public key" debug + message + + Upstream-ID: 964749f820c2ed4cf6a866268b1a05e907315c52 + +commit 066437187e16dcafcbc19f9402ef0e6575899b1d +Author: millert@openbsd.org +Date: Fri Apr 28 03:21:12 2017 +0000 + + upstream commit + + Avoid relying on implementation-specific behavior when + detecting whether the timestamp or file size overflowed. If time_t and off_t + are not either 32-bit or 64-bit scp will exit with an error. OK djm@ + + Upstream-ID: f31caae73ddab6df496b7bbbf7da431e267ad135 + +commit 68d3a2a059183ebd83b15e54984ffaced04d2742 +Author: dtucker@openbsd.org +Date: Fri Apr 28 03:20:27 2017 +0000 + + upstream commit + + Add SyslogFacility option to ssh(1) matching the + equivalent option in sshd(8). bz#2705, patch from erahn at arista.com, ok + djm@ + + Upstream-ID: d5115c2c0193ceb056ed857813b2a7222abda9ed + +commit e13aad66e73a14b062d13aee4e98f1e21a3f6a14 +Author: jsg@openbsd.org +Date: Thu Apr 27 13:40:05 2017 +0000 + + upstream commit + + remove a static array unused since rev 1.306 spotted by + clang ok djm@ + + Upstream-ID: 249b3eed2446f6074ba2219ccc46919dd235a7b8 + +commit 91bd2181866659f00714903e78e1c3edd4c45f3d +Author: millert@openbsd.org +Date: Thu Apr 27 11:53:12 2017 +0000 + + upstream commit + + Avoid potential signed int overflow when parsing the file + size. Use strtoul() instead of parsing manually. OK djm@ + + Upstream-ID: 1f82640861c7d905bbb05e7d935d46b0419ced02 + +commit 17a54a03f5a1d35e33cc24e22cd7a9d0f6865dc4 +Author: Darren Tucker +Date: Tue Apr 25 08:32:27 2017 +1000 + + Fix typo in "socketcall". + + Pointed out by jjelen at redhat.com. + +commit 8b0eee148f7cf8b248c30d1bae57300f2cc5aafd +Author: Darren Tucker +Date: Mon Apr 24 19:40:31 2017 +1000 + + Deny socketcall in seccomp filter on ppc64le. + + OpenSSL is using socket() calls (in FIPS mode) when handling ECDSA keys + in privsep child. The socket() syscall is already denied in the seccomp + filter, but in ppc64le kernel, it is implemented using socketcall() + syscall, which is not denied yet (only SYS_SHUTDOWN is allowed) and + therefore fails hard. + + Patch from jjelen at redhat.com. + +commit f8500b2be599053daa05248a86a743232ec6a536 +Author: schwarze@openbsd.org +Date: Mon Apr 17 14:31:23 2017 +0000 + + upstream commit + + Recognize nl_langinfo(CODESET) return values "646" and "" + as aliases for "US-ASCII", useful for different versions of NetBSD and + Solaris. Found by dtucker@ and by Tom G. Christensen . OK dtucker@ deraadt@ + + Upstream-ID: 38c2133817cbcae75c88c63599ac54228f0fa384 + +commit 7480dfedf8c5c93baaabef444b3def9331e86ad5 +Author: jsg@openbsd.org +Date: Mon Apr 17 11:02:31 2017 +0000 + + upstream commit + + Change COMPILER_VERSION tests which limited additional + warnings to gcc4 to instead skip them on gcc3 as clang can handle + -Wpointer-sign and -Wold-style-definition. + + Upstream-ID: 5cbe348aa76dc1adf55be6c0e388fafaa945439a + +commit 4d827f0d75a53d3952288ab882efbddea7ffadfe +Author: djm@openbsd.org +Date: Tue Apr 4 00:24:56 2017 +0000 + + upstream commit + + disallow creation (of empty files) in read-only mode; + reported by Michal Zalewski, feedback & ok deraadt@ + + Upstream-ID: 5d9c8f2fa8511d4ecf95322994ffe73e9283899b + +commit ef47843af0a904a21c920e619c5aec97b65dd9ac +Author: deraadt@openbsd.org +Date: Sun Mar 26 00:18:52 2017 +0000 + + upstream commit + + incorrect renditions of this quote bother me + + Upstream-ID: 1662be3ebb7a71d543da088119c31d4d463a9e49 + +commit d9048861bea842c4eba9c2dbbf97064cc2a5ef02 +Author: Darren Tucker +Date: Fri Mar 31 11:04:43 2017 +1100 + + Check for and use gcc's -pipe. + + Speeds up configure and build by a couple of percent. ok djm@ + +commit 282cad2240c4fbc104c2f2df86d688192cbbe4bb +Author: Darren Tucker +Date: Wed Mar 29 16:34:44 2017 +1100 + + Import fmt_scaled.c rev 1.16 from OpenBSD. + + Fix overly-conservative overflow checks on mulitplications and add checks + on additions. This allows scan_scaled to work up to +/-LLONG_MAX (LLONG_MIN + will still be flagged as a range error). ok millert@ + +commit c73a229e4edf98920f395e19fd310684fc6bb951 +Author: Darren Tucker +Date: Wed Mar 29 16:34:02 2017 +1100 + + Import fmt_scaled.c rev 1.15 from OpenBSD. + + Collapse underflow and overflow checks into a single block. + ok djm@ millert@ + +commit d427b73bf5a564f663d16546dbcbd84ba8b9d4af +Author: Darren Tucker +Date: Wed Mar 29 16:32:57 2017 +1100 + + Import fmt_scaled.c rev 1.14 from OpenBSD. + + Catch integer underflow in scan_scaled reported by Nicolas Iooss. + ok deraadt@ djm@ + +commit d13281f2964abc5f2e535e1613c77fc61b0c53e7 +Author: Darren Tucker +Date: Wed Mar 29 12:39:39 2017 +1100 + + Don't check privsep user or path when unprivileged + + If running with privsep (mandatory now) as a non-privileged user, we + don't chroot or change to an unprivileged user however we still checked + the existence of the user and directory. Don't do those checks if we're + not going to use them. Based in part on a patch from Lionel Fourquaux + via Corinna Vinschen, ok djm@ + +commit f2742a481fe151e493765a3fbdef200df2ea7037 +Author: Darren Tucker +Date: Wed Mar 29 10:50:31 2017 +1100 + + Remove SHA256 EVP wrapper implementation. + + All supported versions of OpenSSL should now have SHA256 so remove our + EVP wrapper implementaion. ok djm@ + +commit 5346f271fc76549caf4a8e65b5fba319be422fe9 +Author: Darren Tucker +Date: Wed Mar 29 10:23:58 2017 +1100 + + Remove check for OpenSSL < 0.9.8g. + + We no longer support OpenSSL < 1.0.1 so remove check for unreliable ECC + in OpenSSL < 0.9.8g. + +commit 8fed0a5fe7b4e78a6810b133d8e91be9742ee0a1 +Author: Darren Tucker +Date: Wed Mar 29 10:16:15 2017 +1100 + + Remove compat code for OpenSSL < 0.9.7. + + Resyncs that code with OpenBSD upstream. + +commit 608ec1f62ff22fdccc3952e51463d79c43cbd0d3 +Author: Darren Tucker +Date: Wed Mar 29 09:50:54 2017 +1100 + + Remove SSHv1 code path. + + Server-side support for Protocol 1 has been removed so remove !compat20 + PAM code path. + +commit 7af27bf538cbc493d609753f9a6d43168d438f1b +Author: Darren Tucker +Date: Fri Mar 24 09:44:56 2017 +1100 + + Enable ldns when using ldns-config. + + Actually enable ldns when attempting to use ldns-config. bz#2697, patch + from fredrik at fornwall.net. + +commit 58b8cfa2a062b72139d7229ae8de567f55776f24 +Author: Damien Miller +Date: Wed Mar 22 12:43:02 2017 +1100 + + Missing header on Linux/s390 + + Patch from Jakub Jelen + +commit 096fb65084593f9f3c1fc91b6d9052759a272a00 +Author: djm@openbsd.org +Date: Mon Mar 20 22:08:06 2017 +0000 + + upstream commit + + remove /usr/bin/time calls around tests, makes diffing test + runs harder. Based on patch from Mike Frysinger + + Upstream-Regress-ID: 81c1083b14dcf473b23d2817882f40b346ebc95c + +commit 6b853c6f8ba5eecc50f3b57af8e63f8184eb0fa6 +Author: Damien Miller +Date: Tue Mar 21 08:47:55 2017 +1100 + + Fix syntax error on Linux/X32 + + Patch from Mike Frysinger + commit d38f05dbdd291212bc95ea80648b72b7177e9f4e Author: Darren Tucker Date: Mon Mar 20 13:38:27 2017 +1100 @@ -6838,2557 +9349,3 @@ Date: Tue Sep 22 08:33:23 2015 +0000 fix two typos. Upstream-ID: 424402c0d8863a11b51749bacd7f8d932083b709 - -commit 8408218c1ca88cb17d15278174a24a94a6f65fe1 -Author: djm@openbsd.org -Date: Mon Sep 21 04:31:00 2015 +0000 - - upstream commit - - fix possible hang on closed output; bz#2469 reported by Tomas - Kuthan ok markus@ - - Upstream-ID: f7afd41810f8540f524284f1be6b970859f94fe3 - -commit 0097248f90a00865082e8c146b905a6555cc146f -Author: djm@openbsd.org -Date: Fri Sep 11 04:55:01 2015 +0000 - - upstream commit - - skip if running as root; many systems (inc OpenBSD) allow - root to ptrace arbitrary processes - - Upstream-Regress-ID: be2b925df89360dff36f972951fa0fa793769038 - -commit 9c06c814aff925e11a5cc592c06929c258a014f6 -Author: djm@openbsd.org -Date: Fri Sep 11 03:44:21 2015 +0000 - - upstream commit - - try all supported key types here; bz#2455 reported by - Jakub Jelen - - Upstream-Regress-ID: 188cb7d9031cdbac3a0fa58b428b8fa2b2482bba - -commit 3c019a936b43f3e2773f3edbde7c114d73caaa4c -Author: tim@openbsd.org -Date: Sun Sep 13 14:39:16 2015 +0000 - - upstream commit - - - Fix error message: passphrase needs to be at least 5 - characters, not 4. - Remove unused function argument. - Remove two - unnecessary variables. - - OK djm@ - - Upstream-ID: 13010c05bfa8b523da1c0dc19e81dd180662bc30 - -commit 2681cdb6e0de7c1af549dac37a9531af202b4434 -Author: tim@openbsd.org -Date: Sun Sep 13 13:48:19 2015 +0000 - - upstream commit - - When adding keys to the agent, don't ignore the comment - of keys for which the user is prompted for a passphrase. - - Tweak and OK djm@ - - Upstream-ID: dc737c620a5a8d282cc4f66e3b9b624e9abefbec - -commit 14692f7b8251cdda847e648a82735eef8a4d2a33 -Author: guenther@openbsd.org -Date: Fri Sep 11 08:50:04 2015 +0000 - - upstream commit - - Use explicit_bzero() when zeroing before free() - - from Michael McConville (mmcconv1 (at) sccs.swarthmore.edu) - ok millert@ djm@ - - Upstream-ID: 2e3337db046c3fe70c7369ee31515ac73ec00f50 - -commit 846f6fa4cfa8483a9195971dbdd162220f199d85 -Author: jmc@openbsd.org -Date: Fri Sep 11 06:55:46 2015 +0000 - - upstream commit - - sync -Q in usage() to SYNOPSIS; since it's drastically - shorter, i've reformatted the block to sync with the man (80 cols) and saved - a line; - - Upstream-ID: 86e2c65c3989a0777a6258a77e589b9f6f354abd - -commit 95923e0520a8647417ee6dcdff44694703dfeef0 -Author: jmc@openbsd.org -Date: Fri Sep 11 06:51:39 2015 +0000 - - upstream commit - - tweak previous; - - Upstream-ID: f29b3cfcfd9aa31fa140c393e7bd48c1c74139d6 - -commit 86ac462f833b05d8ed9de9c50ccb295d7faa79ff -Author: dtucker@openbsd.org -Date: Fri Sep 11 05:27:02 2015 +0000 - - upstream commit - - Update usage to match man page. - - Upstream-ID: 9e85aefaecfb6aaf34c7cfd0700cd21783a35675 - -commit 674b3b68c1d36b2562324927cd03857b565e05e8 -Author: djm@openbsd.org -Date: Fri Sep 11 03:47:28 2015 +0000 - - upstream commit - - expand %i in ControlPath to UID; bz#2449 - - patch from Christian Hesse w/ feedback from dtucker@ - - Upstream-ID: 2ba8d303e555a84e2f2165ab4b324b41e80ab925 - -commit c0f55db7ee00c8202b05cb4b9ad4ce72cc45df41 -Author: djm@openbsd.org -Date: Fri Sep 11 03:42:32 2015 +0000 - - upstream commit - - mention -Q key-plain and -Q key-cert; bz#2455 pointed out - by Jakub Jelen - - Upstream-ID: c8f1f8169332e4fa73ac96b0043e3b84e01d4896 - -commit cfffbdb10fdf0f02d3f4232232eef7ec3876c383 -Author: Darren Tucker -Date: Mon Sep 14 16:24:21 2015 +1000 - - Use ssh-keygen -A when generating host keys. - - Use ssh-keygen -A instead of per-keytype invocations when generating host - keys. Add tests when doing host-key-force since we can't use ssh-keygen -A - since it can't specify alternate locations. bz#2459, ok djm@ - -commit 366bada1e9e124654aac55b72b6ccf878755b0dc -Author: Darren Tucker -Date: Fri Sep 11 13:29:22 2015 +1000 - - Correct default value for --with-ssh1. - - bz#2457, from konto-mindrot.org at walimnieto.com. - -commit 2bca8a43e7dd9b04d7070824ffebb823c72587b2 -Author: djm@openbsd.org -Date: Fri Sep 11 03:13:36 2015 +0000 - - upstream commit - - more clarity on what AuthorizedKeysFile=none does; based - on diff by Thiebaud Weksteen - - Upstream-ID: 78ab87f069080f0cc3bc353bb04eddd9e8ad3704 - -commit 61942ea4a01e6db4fdf37ad61de81312ffe310e9 -Author: djm@openbsd.org -Date: Wed Sep 9 00:52:44 2015 +0000 - - upstream commit - - openssh_RSA_verify return type is int, so don't make it - size_t within the function itself with only negative numbers or zero assigned - to it. bz#2460 - - Upstream-ID: b6e794b0c7fc4f9f329509263c8668d35f83ea55 - -commit 4f7cc2f8cc861a21e6dbd7f6c25652afb38b9b96 -Author: dtucker@openbsd.org -Date: Fri Sep 4 08:21:47 2015 +0000 - - upstream commit - - Plug minor memory leaks when options are used more than - once. bz#2182, patch from Tiago Cunha, ok deraadt djm - - Upstream-ID: 5b84d0401e27fe1614c10997010cc55933adb48e - -commit 7ad8b287c8453a3e61dbc0d34d467632b8b06fc8 -Author: Darren Tucker -Date: Fri Sep 11 13:11:02 2015 +1000 - - Force resolution of _res for correct detection. - - bz#2259, from sconeu at yahoo.com. - -commit 26ad18247213ff72b4438abe7fc660c958810fa2 -Author: Damien Miller -Date: Thu Sep 10 10:57:41 2015 +1000 - - allow getrandom syscall; from Felix von Leitner - -commit 5245bc1e6b129a10a928f73f11c3aa32656c44b4 -Author: jmc@openbsd.org -Date: Fri Sep 4 06:40:45 2015 +0000 - - upstream commit - - full stop belongs outside the brackets, not inside; - - Upstream-ID: 99d098287767799ac33d2442a05b5053fa5a551a - -commit a85768a9321d74b41219eeb3c9be9f1702cbf6a5 -Author: djm@openbsd.org -Date: Fri Sep 4 04:56:09 2015 +0000 - - upstream commit - - add a debug2() right before DNS resolution; it's a place - where ssh could previously silently hang for a while. bz#2433 - - Upstream-ID: 52a1a3e0748db66518e7598352c427145692a6a0 - -commit 46152af8d27aa34d5d26ed1c371dc8aa142d4730 -Author: djm@openbsd.org -Date: Fri Sep 4 04:55:24 2015 +0000 - - upstream commit - - correct function name in error messages - - Upstream-ID: 92fb2798617ad9561370897f4ab60adef2ff4c0e - -commit a954cdb799a4d83c2d40fbf3e7b9f187fbfd72fc -Author: djm@openbsd.org -Date: Fri Sep 4 04:47:50 2015 +0000 - - upstream commit - - better document ExitOnForwardFailure; bz#2444, ok - dtucker@ - - Upstream-ID: a126209b5a6d9cb3117ac7ab5bc63d284538bfc2 - -commit f54d8ac2474b6fc3afa081cf759b48a6c89d3319 -Author: djm@openbsd.org -Date: Fri Sep 4 04:44:08 2015 +0000 - - upstream commit - - don't record hostbased authentication hostkeys as user - keys in test for multiple authentication with the same key - - Upstream-ID: 26b368fa2cff481f47f37e01b8da1ae5b57b1adc - -commit ac3451dd65f27ecf85dc045c46d49e2bbcb8dddd -Author: djm@openbsd.org -Date: Fri Sep 4 03:57:38 2015 +0000 - - upstream commit - - remove extra newline in nethack-mode hostkey; from - Christian Hesse bz#2686 - - Upstream-ID: 4f56368b1cc47baeea0531912186f66007fd5b92 - -commit 9e3ed9ebb1a7e47c155c28399ddf09b306ea05df -Author: djm@openbsd.org -Date: Fri Sep 4 04:23:10 2015 +0000 - - upstream commit - - trim junk from end of file; bz#2455 from Jakub Jelen - - Upstream-Regress-ID: a4e64e8931e40d23874b047074444eff919cdfe6 - -commit f3a3ea180afff080bab82087ee0b60db9fd84f6c -Author: jsg@openbsd.org -Date: Wed Sep 2 07:51:12 2015 +0000 - - upstream commit - - Fix occurrences of "r = func() != 0" which result in the - wrong error codes being returned due to != having higher precedence than =. - - ok deraadt@ markus@ - - Upstream-ID: 5fc35c9fc0319cc6fca243632662d2f06b5fd840 - -commit f498a98cf83feeb7ea01c15cd1c98b3111361f3a -Author: Damien Miller -Date: Thu Sep 3 09:11:22 2015 +1000 - - don't check for yp_match; ok tim@ - -commit 9690b78b7848b0b376980a61d51b1613e187ddb5 -Author: djm@openbsd.org -Date: Fri Aug 21 23:57:48 2015 +0000 - - upstream commit - - Improve printing of KEX offers and decisions - - The debug output now labels the client and server offers and the - negotiated options. ok markus@ - - Upstream-ID: 8db921b3f92a4565271b1c1fbce6e7f508e1a2cb - -commit 60a92470e21340e1a3fc10f9c7140d8e1519dc55 -Author: djm@openbsd.org -Date: Fri Aug 21 23:53:08 2015 +0000 - - upstream commit - - Fix printing (ssh -G ...) of HostKeyAlgorithms=+... - Reported by Bryan Drewery - - Upstream-ID: 19ad20c41bd5971e006289b6f9af829dd46c1293 - -commit 6310f60fffca2d1e464168e7d1f7e3b6b0268897 -Author: djm@openbsd.org -Date: Fri Aug 21 23:52:30 2015 +0000 - - upstream commit - - Fix expansion of HostkeyAlgorithms=+... - - Reported by Bryan Drewery - - Upstream-ID: 70ca1deea39d758ba36d36428ae832e28566f78d - -commit e774e5ea56237fd626a8161f9005023dff3e76c9 -Author: deraadt@openbsd.org -Date: Fri Aug 21 23:29:31 2015 +0000 - - upstream commit - - Improve size == 0, count == 0 checking in mm_zalloc, - which is "array" like. Discussed with tedu, millert, otto.... and ok djm - - Upstream-ID: 899b021be43b913fad3eca1aef44efe710c53e29 - -commit 189de02d9ad6f3645417c0ddf359b923aae5f926 -Author: Damien Miller -Date: Fri Aug 21 15:45:02 2015 +1000 - - expose POLLHUP and POLLNVAL for netcat.c - -commit e91346dc2bbf460246df2ab591b7613908c1b0ad -Author: Damien Miller -Date: Fri Aug 21 14:49:03 2015 +1000 - - we don't use Github for issues/pull-requests - -commit a4f5b507c708cc3dc2c8dd2d02e4416d7514dc23 -Author: Damien Miller -Date: Fri Aug 21 14:43:55 2015 +1000 - - fix URL for connect.c - -commit d026a8d3da0f8186598442997c7d0a28e7275414 -Author: Damien Miller -Date: Fri Aug 21 13:47:10 2015 +1000 - - update version numbers for 7.1 - -commit 78f8f589f0ca1c9f41e5a9bae3cda5ce8a6b42ed -Author: djm@openbsd.org -Date: Fri Aug 21 03:45:26 2015 +0000 - - upstream commit - - openssh-7.1 - - Upstream-ID: ff7b1ef4b06caddfb45e08ba998128c88be3d73f - -commit 32a181980c62fce94f7f9ffaf6a79d90f0c309cf -Author: djm@openbsd.org -Date: Fri Aug 21 03:42:19 2015 +0000 - - upstream commit - - fix inverted logic that broke PermitRootLogin; reported - by Mantas Mikulenas; ok markus@ - - Upstream-ID: 260dd6a904c1bb7e43267e394b1c9cf70bdd5ea5 - -commit ce445b0ed927e45bd5bdce8f836eb353998dd65c -Author: deraadt@openbsd.org -Date: Thu Aug 20 22:32:42 2015 +0000 - - upstream commit - - Do not cast result of malloc/calloc/realloc* if stdlib.h - is in scope ok krw millert - - Upstream-ID: 5e50ded78cadf3841556649a16cc4b1cb6c58667 - -commit 05291e5288704d1a98bacda269eb5a0153599146 -Author: naddy@openbsd.org -Date: Thu Aug 20 19:20:06 2015 +0000 - - upstream commit - - In the certificates section, be consistent about using - "host_key" and "user_key" for the respective key types. ok sthen@ deraadt@ - - Upstream-ID: 9e037ea3b15577b238604c5533e082a3947f13cb - -commit 8543d4ef6f2e9f98c3e6b77c894ceec30c5e4ae4 -Author: djm@openbsd.org -Date: Wed Aug 19 23:21:42 2015 +0000 - - upstream commit - - Better compat matching for WinSCP, add compat matching - for FuTTY (fork of PuTTY); ok markus@ deraadt@ - - Upstream-ID: 24001d1ac115fa3260fbdc329a4b9aeb283c5389 - -commit ec6eda16ebab771aa3dfc90629b41953b999cb1e -Author: djm@openbsd.org -Date: Wed Aug 19 23:19:01 2015 +0000 - - upstream commit - - fix double-free() in error path of DSA key generation - reported by Mateusz Kocielski; ok markus@ - - Upstream-ID: 4735d8f888b10599a935fa1b374787089116713c - -commit 45b0eb752c94954a6de046bfaaf129e518ad4b5b -Author: djm@openbsd.org -Date: Wed Aug 19 23:18:26 2015 +0000 - - upstream commit - - fix free() of uninitialised pointer reported by Mateusz - Kocielski; ok markus@ - - Upstream-ID: 519552b050618501a06b7b023de5cb104e2c5663 - -commit c837643b93509a3ef538cb6624b678c5fe32ff79 -Author: djm@openbsd.org -Date: Wed Aug 19 23:17:51 2015 +0000 - - upstream commit - - fixed unlink([uninitialised memory]) reported by Mateusz - Kocielski; ok markus@ - - Upstream-ID: 14a0c4e7d891f5a8dabc4b89d4f6b7c0d5a20109 - -commit 1f8d3d629cd553031021068eb9c646a5f1e50994 -Author: jmc@openbsd.org -Date: Fri Aug 14 15:32:41 2015 +0000 - - upstream commit - - match myproposal.h order; from brian conway (i snuck in a - tweak while here) - - ok dtucker - - Upstream-ID: 35174a19b5237ea36aa3798f042bf5933b772c67 - -commit 1dc8d93ce69d6565747eb44446ed117187621b26 -Author: deraadt@openbsd.org -Date: Thu Aug 6 14:53:21 2015 +0000 - - upstream commit - - add prohibit-password as a synonymn for without-password, - since the without-password is causing too many questions. Harden it to ban - all but pubkey, hostbased, and GSSAPI auth (when the latter is enabled) from - djm, ok markus - - Upstream-ID: d53317d7b28942153e6236d3fd6e12ceb482db7a - -commit 90a95a4745a531b62b81ce3b025e892bdc434de5 -Author: Damien Miller -Date: Tue Aug 11 13:53:41 2015 +1000 - - update version in README - -commit 318c37743534b58124f1bab37a8a0087a3a9bd2f -Author: Damien Miller -Date: Tue Aug 11 13:53:09 2015 +1000 - - update versions in *.spec - -commit 5e75f5198769056089fb06c4d738ab0e5abc66f7 -Author: Damien Miller -Date: Tue Aug 11 13:34:12 2015 +1000 - - set sshpam_ctxt to NULL after free - - Avoids use-after-free in monitor when privsep child is compromised. - Reported by Moritz Jodeit; ok dtucker@ - -commit d4697fe9a28dab7255c60433e4dd23cf7fce8a8b -Author: Damien Miller -Date: Tue Aug 11 13:33:24 2015 +1000 - - Don't resend username to PAM; it already has it. - - Pointed out by Moritz Jodeit; ok dtucker@ - -commit 88763a6c893bf3dfe951ba9271bf09715e8d91ca -Author: Darren Tucker -Date: Mon Jul 27 12:14:25 2015 +1000 - - Import updated moduli file from OpenBSD. - -commit 55b263fb7cfeacb81aaf1c2036e0394c881637da -Author: Damien Miller -Date: Mon Aug 10 11:13:44 2015 +1000 - - let principals-command.sh work for noexec /var/run - -commit 2651e34cd11b1aac3a0fe23b86d8c2ff35c07897 -Author: Damien Miller -Date: Thu Aug 6 11:43:42 2015 +1000 - - work around echo -n / sed behaviour in tests - -commit d85dad81778c1aa8106acd46930b25fdf0d15b2a -Author: djm@openbsd.org -Date: Wed Aug 5 05:27:33 2015 +0000 - - upstream commit - - adjust for RSA minimum modulus switch; ok deraadt@ - - Upstream-Regress-ID: 5a72c83431b96224d583c573ca281cd3a3ebfdae - -commit 57e8e229bad5fe6056b5f1199665f5f7008192c6 -Author: djm@openbsd.org -Date: Tue Aug 4 05:23:06 2015 +0000 - - upstream commit - - backout SSH_RSA_MINIMUM_MODULUS_SIZE increase for this - release; problems spotted by sthen@ ok deraadt@ markus@ - - Upstream-ID: d0bd60dde9e8c3cd7030007680371894c1499822 - -commit f097d0ea1e0889ca0fa2e53a00214e43ab7fa22a -Author: djm@openbsd.org -Date: Sun Aug 2 09:56:42 2015 +0000 - - upstream commit - - openssh 7.0; ok deraadt@ - - Upstream-ID: c63afdef537f57f28ae84145c5a8e29e9250221f - -commit 3d5728a0f6874ce4efb16913a12963595070f3a9 -Author: chris@openbsd.org -Date: Fri Jul 31 15:38:09 2015 +0000 - - upstream commit - - Allow PermitRootLogin to be overridden by config - - ok markus@ deeradt@ - - Upstream-ID: 5cf3e26ed702888de84e2dc9d0054ccf4d9125b4 - -commit 6f941396b6835ad18018845f515b0c4fe20be21a -Author: djm@openbsd.org -Date: Thu Jul 30 23:09:15 2015 +0000 - - upstream commit - - fix pty permissions; patch from Nikolay Edigaryev; ok - deraadt - - Upstream-ID: 40ff076d2878b916fbfd8e4f45dbe5bec019e550 - -commit f4373ed1e8fbc7c8ce3fc4ea97d0ba2e0c1d7ef0 -Author: deraadt@openbsd.org -Date: Thu Jul 30 19:23:02 2015 +0000 - - upstream commit - - change default: PermitRootLogin without-password matching - install script changes coming as well ok djm markus - - Upstream-ID: 0e2a6c4441daf5498b47a61767382bead5eb8ea6 - -commit 0c30ba91f87fcda7e975e6ff8a057f624e87ea1c -Author: Damien Miller -Date: Thu Jul 30 12:31:39 2015 +1000 - - downgrade OOM adjustment logging: verbose -> debug - -commit f9eca249d4961f28ae4b09186d7dc91de74b5895 -Author: djm@openbsd.org -Date: Thu Jul 30 00:01:34 2015 +0000 - - upstream commit - - Allow ssh_config and sshd_config kex parameters options be - prefixed by a '+' to indicate that the specified items be appended to the - default rather than replacing it. - - approach suggested by dtucker@, feedback dlg@, ok markus@ - - Upstream-ID: 0f901137298fc17095d5756ff1561a7028e8882a - -commit 5cefe769105a2a2e3ca7479d28d9a325d5ef0163 -Author: djm@openbsd.org -Date: Wed Jul 29 08:34:54 2015 +0000 - - upstream commit - - fix bug in previous; was printing incorrect string for - failed host key algorithms negotiation - - Upstream-ID: 22c0dc6bc61930513065d92e11f0753adc4c6e6e - -commit f319912b0d0e1675b8bb051ed8213792c788bcb2 -Author: djm@openbsd.org -Date: Wed Jul 29 04:43:06 2015 +0000 - - upstream commit - - include the peer's offer when logging a failure to - negotiate a mutual set of algorithms (kex, pubkey, ciphers, etc.) ok markus@ - - Upstream-ID: bbb8caabf5c01790bb845f5ce135565248d7c796 - -commit b6ea0e573042eb85d84defb19227c89eb74cf05a -Author: djm@openbsd.org -Date: Tue Jul 28 23:20:42 2015 +0000 - - upstream commit - - add Cisco to the list of clients that choke on the - hostkeys update extension. Pointed out by Howard Kash - - Upstream-ID: c9eadde28ecec056c73d09ee10ba4570dfba7e84 - -commit 3f628c7b537291c1019ce86af90756fb4e66d0fd -Author: guenther@openbsd.org -Date: Mon Jul 27 16:29:23 2015 +0000 - - upstream commit - - Permit kbind(2) use in the sandbox now, to ease testing - of ld.so work using it - - reminded by miod@, ok deraadt@ - - Upstream-ID: 523922e4d1ba7a091e3824e77a8a3c818ee97413 - -commit ebe27ebe520098bbc0fe58945a87ce8490121edb -Author: millert@openbsd.org -Date: Mon Jul 20 18:44:12 2015 +0000 - - upstream commit - - Move .Pp before .Bl, not after to quiet mandoc -Tlint. - Noticed by jmc@ - - Upstream-ID: 59fadbf8407cec4e6931e50c53cfa0214a848e23 - -commit d5d91d0da819611167782c66ab629159169d94d4 -Author: millert@openbsd.org -Date: Mon Jul 20 18:42:35 2015 +0000 - - upstream commit - - Sync usage with SYNOPSIS - - Upstream-ID: 7a321a170181a54f6450deabaccb6ef60cf3f0b7 - -commit 79ec2142fbc68dd2ed9688608da355fc0b1ed743 -Author: millert@openbsd.org -Date: Mon Jul 20 15:39:52 2015 +0000 - - upstream commit - - Better desciption of Unix domain socket forwarding. - bz#2423; ok jmc@ - - Upstream-ID: 85e28874726897e3f26ae50dfa2e8d2de683805d - -commit d56fd1828074a4031b18b8faa0bf949669eb18a0 -Author: Damien Miller -Date: Mon Jul 20 11:19:51 2015 +1000 - - make realpath.c compile -Wsign-compare clean - -commit c63c9a691dca26bb7648827f5a13668832948929 -Author: djm@openbsd.org -Date: Mon Jul 20 00:30:01 2015 +0000 - - upstream commit - - mention that the default of UseDNS=no implies that - hostnames cannot be used for host matching in sshd_config and - authorized_keys; bz#2045, ok dtucker@ - - Upstream-ID: 0812705d5f2dfa59aab01f2764ee800b1741c4e1 - -commit 63ebcd0005e9894fcd6871b7b80aeea1fec0ff76 -Author: djm@openbsd.org -Date: Sat Jul 18 08:02:17 2015 +0000 - - upstream commit - - don't ignore PKCS#11 hosted keys that return empty - CKA_ID; patch by Jakub Jelen via bz#2429; ok markus - - Upstream-ID: 2f7c94744eb0342f8ee8bf97b2351d4e00116485 - -commit b15fd989c8c62074397160147a8d5bc34b3f3c63 -Author: djm@openbsd.org -Date: Sat Jul 18 08:00:21 2015 +0000 - - upstream commit - - skip uninitialised PKCS#11 slots; patch from Jakub Jelen - in bz#2427 ok markus@ - - Upstream-ID: 744c1e7796e237ad32992d0d02148e8a18f27d29 - -commit 5b64f85bb811246c59ebab70aed331f26ba37b18 -Author: djm@openbsd.org -Date: Sat Jul 18 07:57:14 2015 +0000 - - upstream commit - - only query each keyboard-interactive device once per - authentication request regardless of how many times it is listed; ok markus@ - - Upstream-ID: d73fafba6e86030436ff673656ec1f33d9ffeda1 - -commit cd7324d0667794eb5c236d8a4e0f236251babc2d -Author: djm@openbsd.org -Date: Fri Jul 17 03:34:27 2015 +0000 - - upstream commit - - remove -u flag to diff (only used for error output) to make - things easier for -portable - - Upstream-Regress-ID: a5d6777d2909540d87afec3039d9bb2414ade548 - -commit deb8d99ecba70b67f4af7880b11ca8768df9ec3a -Author: djm@openbsd.org -Date: Fri Jul 17 03:09:19 2015 +0000 - - upstream commit - - direct-streamlocal@openssh.com Unix domain foward - messages do not contain a "reserved for future use" field and in fact, - serverloop.c checks that there isn't one. Remove erroneous mention from - PROTOCOL description. bz#2421 from Daniel Black - - Upstream-ID: 3d51a19e64f72f764682f1b08f35a8aa810a43ac - -commit 356b61f365405b5257f5b2ab446e5d7bd33a7b52 -Author: djm@openbsd.org -Date: Fri Jul 17 03:04:27 2015 +0000 - - upstream commit - - describe magic for setting up Unix domain socket fowards - via the mux channel; bz#2422 patch from Daniel Black - - Upstream-ID: 943080fe3864715c423bdeb7c920bb30c4eee861 - -commit d3e2aee41487d55b8d7d40f538b84ff1db7989bc -Author: Darren Tucker -Date: Fri Jul 17 12:52:34 2015 +1000 - - Check if realpath works on nonexistent files. - - On some platforms the native realpath doesn't work with non-existent - files (this is actually specified in some versions of POSIX), however - the sftp spec says its realpath with "canonicalize any given path name". - On those platforms, use realpath from the compat library. - - In addition, when compiling with -DFORTIFY_SOURCE, glibc redefines - the realpath symbol to the checked version, so redefine ours to - something else so we pick up the compat version we want. - - bz#2428, ok djm@ - -commit 25b14610dab655646a109db5ef8cb4c4bf2a48a0 -Author: djm@openbsd.org -Date: Fri Jul 17 02:47:45 2015 +0000 - - upstream commit - - fix incorrect test for SSH1 keys when compiled without SSH1 - support - - Upstream-ID: 6004d720345b8e481c405e8ad05ce2271726e451 - -commit df56a8035d429b2184ee94aaa7e580c1ff67f73a -Author: djm@openbsd.org -Date: Wed Jul 15 08:00:11 2015 +0000 - - upstream commit - - fix NULL-deref when SSH1 reenabled - - Upstream-ID: f22fd805288c92b3e9646782d15b48894b2d5295 - -commit 41e38c4d49dd60908484e6703316651333f16b93 -Author: djm@openbsd.org -Date: Wed Jul 15 07:19:50 2015 +0000 - - upstream commit - - regen RSA1 test keys; the last batch was missing their - private parts - - Upstream-Regress-ID: 7ccf437305dd63ff0b48dd50c5fd0f4d4230c10a - -commit 5bf0933184cb622ca3f96d224bf3299fd2285acc -Author: markus@openbsd.org -Date: Fri Jul 10 06:23:25 2015 +0000 - - upstream commit - - Adapt tests, now that DSA if off by default; use - PubkeyAcceptedKeyTypes and PubkeyAcceptedKeyTypes to test DSA. - - Upstream-Regress-ID: 0ff2a3ff5ac1ce5f92321d27aa07b98656efcc5c - -commit 7a6e3fd7b41dbd3756b6bf9acd67954c0b1564cc -Author: markus@openbsd.org -Date: Tue Jul 7 14:54:16 2015 +0000 - - upstream commit - - regen test data after mktestdata.sh changes - - Upstream-Regress-ID: 3495ecb082b9a7c048a2d7c5c845d3bf181d25a4 - -commit 7c8c174c69f681d4910fa41c37646763692b28e2 -Author: markus@openbsd.org -Date: Tue Jul 7 14:53:30 2015 +0000 - - upstream commit - - adapt tests to new minimum RSA size and default FP format - - Upstream-Regress-ID: a4b30afd174ce82b96df14eb49fb0b81398ffd0e - -commit 6a977a4b68747ade189e43d302f33403fd4a47ac -Author: djm@openbsd.org -Date: Fri Jul 3 04:39:23 2015 +0000 - - upstream commit - - legacy v00 certificates are gone; adapt and don't try to - test them; "sure" markus@ dtucker@ - - Upstream-Regress-ID: c57321e69b3cd4a3b3396dfcc43f0803d047da12 - -commit 0c4123ad5e93fb90fee9c6635b13a6cdabaac385 -Author: djm@openbsd.org -Date: Wed Jul 1 23:11:18 2015 +0000 - - upstream commit - - don't expect SSH v.1 in unittests - - Upstream-Regress-ID: f8812b16668ba78e6a698646b2a652b90b653397 - -commit 3c099845798a817cdde513c39074ec2063781f18 -Author: djm@openbsd.org -Date: Mon Jun 15 06:38:50 2015 +0000 - - upstream commit - - turn SSH1 back on to match src/usr.bin/ssh being tested - - Upstream-Regress-ID: 6c4f763a2f0cc6893bf33983919e9030ae638333 - -commit b1dc2b33689668c75e95f873a42d5aea1f4af1db -Author: dtucker@openbsd.org -Date: Mon Jul 13 04:57:14 2015 +0000 - - upstream commit - - Add "PuTTY_Local:" to the clients to which we do not - offer DH-GEX. This was the string that was used for development versions - prior to September 2014 and they don't do RFC4419 DH-GEX, but unfortunately - there are some extant products based on those versions. bx2424 from Jay - Rouman, ok markus@ djm@ - - Upstream-ID: be34d41e18b966832fe09ca243d275b81882e1d5 - -commit 3a1638dda19bbc73d0ae02b4c251ce08e564b4b9 -Author: markus@openbsd.org -Date: Fri Jul 10 06:21:53 2015 +0000 - - upstream commit - - Turn off DSA by default; add HostKeyAlgorithms to the - server and PubkeyAcceptedKeyTypes to the client side, so it still can be - tested or turned back on; feedback and ok djm@ - - Upstream-ID: 8450a9e6d83f80c9bfed864ff061dfc9323cec21 - -commit 16db0a7ee9a87945cc594d13863cfcb86038db59 -Author: markus@openbsd.org -Date: Thu Jul 9 09:49:46 2015 +0000 - - upstream commit - - re-enable ed25519-certs if compiled w/o openssl; ok djm - - Upstream-ID: e10c90808b001fd2c7a93778418e9b318f5c4c49 - -commit c355bf306ac33de6545ce9dac22b84a194601e2f -Author: markus@openbsd.org -Date: Wed Jul 8 20:24:02 2015 +0000 - - upstream commit - - no need to include the old buffer/key API - - Upstream-ID: fb13c9f7c0bba2545f3eb0a0e69cb0030819f52b - -commit a3cc48cdf9853f1e832d78cb29bedfab7adce1ee -Author: markus@openbsd.org -Date: Wed Jul 8 19:09:25 2015 +0000 - - upstream commit - - typedefs for Cipher&CipherContext are unused - - Upstream-ID: 50e6a18ee92221d23ad173a96d5b6c42207cf9a7 - -commit a635bd06b5c427a57c3ae760d3a2730bb2c863c0 -Author: markus@openbsd.org -Date: Wed Jul 8 19:04:21 2015 +0000 - - upstream commit - - xmalloc.h is unused - - Upstream-ID: afb532355b7fa7135a60d944ca1e644d1d63cb58 - -commit 2521cf0e36c7f3f6b19f206da0af134f535e4a31 -Author: markus@openbsd.org -Date: Wed Jul 8 19:01:15 2015 +0000 - - upstream commit - - compress.c is gone - - Upstream-ID: 174fa7faa9b9643cba06164b5e498591356fbced - -commit c65a7aa6c43aa7a308ee1ab8a96f216169ae9615 -Author: djm@openbsd.org -Date: Fri Jul 3 04:05:54 2015 +0000 - - upstream commit - - another SSH_RSA_MINIMUM_MODULUS_SIZE that needed - cranking - - Upstream-ID: 9d8826cafe96aab4ae8e2f6fd22800874b7ffef1 - -commit b1f383da5cd3cb921fc7776f17a14f44b8a31757 -Author: djm@openbsd.org -Date: Fri Jul 3 03:56:25 2015 +0000 - - upstream commit - - add an XXX reminder for getting correct key paths from - sshd_config - - Upstream-ID: feae52b209d7782ad742df04a4260e9fe41741db - -commit 933935ce8d093996c34d7efa4d59113163080680 -Author: djm@openbsd.org -Date: Fri Jul 3 03:49:45 2015 +0000 - - upstream commit - - refuse to generate or accept RSA keys smaller than 1024 - bits; feedback and ok dtucker@ - - Upstream-ID: 7ea3d31271366ba264f06e34a3539bf1ac30f0ba - -commit bdfd29f60b74f3e678297269dc6247a5699583c1 -Author: djm@openbsd.org -Date: Fri Jul 3 03:47:00 2015 +0000 - - upstream commit - - turn off 1024 bit diffie-hellman-group1-sha1 key - exchange method (already off in server, this turns it off in the client by - default too) ok dtucker@ - - Upstream-ID: f59b88f449210ab7acf7d9d88f20f1daee97a4fa - -commit c28fc62d789d860c75e23a9fa9fb250eb2beca57 -Author: djm@openbsd.org -Date: Fri Jul 3 03:43:18 2015 +0000 - - upstream commit - - delete support for legacy v00 certificates; "sure" - markus@ dtucker@ - - Upstream-ID: b5b9bb5f9202d09e88f912989d74928601b6636f - -commit 564d63e1b4a9637a209d42a9d49646781fc9caef -Author: djm@openbsd.org -Date: Wed Jul 1 23:10:47 2015 +0000 - - upstream commit - - Compile-time disable SSH v.1 again - - Upstream-ID: 1d4b513a3a06232f02650b73bad25100d1b800af - -commit 868109b650504dd9bcccdb1f51d0906f967c20ff -Author: djm@openbsd.org -Date: Wed Jul 1 02:39:06 2015 +0000 - - upstream commit - - twiddle PermitRootLogin back - - Upstream-ID: 2bd23976305d0512e9f84d054e1fc23cd70b89f2 - -commit 7de4b03a6e4071d454b72927ffaf52949fa34545 -Author: djm@openbsd.org -Date: Wed Jul 1 02:32:17 2015 +0000 - - upstream commit - - twiddle; (this commit marks the openssh-6.9 release) - - Upstream-ID: 78500582819f61dd8adee36ec5cc9b9ac9351234 - -commit 1bf477d3cdf1a864646d59820878783d42357a1d -Author: djm@openbsd.org -Date: Wed Jul 1 02:26:31 2015 +0000 - - upstream commit - - better refuse ForwardX11Trusted=no connections attempted - after ForwardX11Timeout expires; reported by Jann Horn - - Upstream-ID: bf0fddadc1b46a0334e26c080038313b4b6dea21 - -commit 47aa7a0f8551b471fcae0447c1d78464f6dba869 -Author: djm@openbsd.org -Date: Wed Jul 1 01:56:13 2015 +0000 - - upstream commit - - put back default PermitRootLogin=no - - Upstream-ID: 7bdedd5cead99c57ed5571f3b6b7840922d5f728 - -commit 984b064fe2a23733733262f88d2e1b2a1a501662 -Author: djm@openbsd.org -Date: Wed Jul 1 01:55:13 2015 +0000 - - upstream commit - - openssh-6.9 - - Upstream-ID: 6cfe8e1904812531080e6ab6e752d7001b5b2d45 - -commit d921082ed670f516652eeba50705e1e9f6325346 -Author: djm@openbsd.org -Date: Wed Jul 1 01:55:00 2015 +0000 - - upstream commit - - reset default PermitRootLogin to 'yes' (momentarily, for - release) - - Upstream-ID: cad8513527066e65dd7a1c16363d6903e8cefa24 - -commit 66295e0e1ba860e527f191b6325d2d77dec4dbce -Author: Damien Miller -Date: Wed Jul 1 11:49:12 2015 +1000 - - crank version numbers for release - -commit 37035c07d4f26bb1fbe000d2acf78efdb008681d -Author: Damien Miller -Date: Wed Jul 1 10:49:37 2015 +1000 - - s/--with-ssh1/--without-ssh1/ - -commit 629df770dbadc2accfbe1c81b3f31f876d0acd84 -Author: djm@openbsd.org -Date: Tue Jun 30 05:25:07 2015 +0000 - - upstream commit - - fatal() when a remote window update causes the window - value to overflow. Reported by Georg Wicherski, ok markus@ - - Upstream-ID: ead397a9aceb3bf74ebfa5fcaf259d72e569f351 - -commit f715afebe735d61df3fd30ad72d9ac1c8bd3b5f2 -Author: djm@openbsd.org -Date: Tue Jun 30 05:23:25 2015 +0000 - - upstream commit - - Fix math error in remote window calculations that causes - eventual stalls for datagram channels. Reported by Georg Wicherski, ok - markus@ - - Upstream-ID: be54059d11bf64e0d85061f7257f53067842e2ab - -commit 52fb6b9b034fcfd24bf88cc7be313e9c31de9889 -Author: Damien Miller -Date: Tue Jun 30 16:05:40 2015 +1000 - - skip IPv6-related portions on hosts without IPv6 - - with Tim Rice - -commit 512caddf590857af6aa12218461b5c0441028cf5 -Author: djm@openbsd.org -Date: Mon Jun 29 22:35:12 2015 +0000 - - upstream commit - - add getpid to sandbox, reachable by grace_alarm_handler - - reported by Jakub Jelen; bz#2419 - - Upstream-ID: d0da1117c16d4c223954995d35b0f47c8f684cd8 - -commit 78c2a4f883ea9aba866358e2acd9793a7f42ca93 -Author: djm@openbsd.org -Date: Fri Jun 26 05:13:20 2015 +0000 - - upstream commit - - Fix \-escaping bug that caused forward path parsing to skip - two characters and skip past the end of the string. - - Based on patch by Salvador Fandino; ok dtucker@ - - Upstream-ID: 7b879dc446335677cbe4cb549495636a0535f3bd - -commit bc20205c91c9920361d12b15d253d4997dba494a -Author: Damien Miller -Date: Thu Jun 25 09:51:39 2015 +1000 - - add missing pselect6 - - patch from Jakub Jelen - -commit 9d27fb73b4a4e5e99cb880af790d5b1ce44f720a -Author: djm@openbsd.org -Date: Wed Jun 24 23:47:23 2015 +0000 - - upstream commit - - correct test to sshkey_sign(); spotted by Albert S. - - Upstream-ID: 5f7347f40f0ca6abdaca2edb3bd62f4776518933 - -commit 7ed01a96a1911d8b4a9ef4f3d064e1923bfad7e3 -Author: dtucker@openbsd.org -Date: Wed Jun 24 01:49:19 2015 +0000 - - upstream commit - - Revert previous commit. We still want to call setgroups - in the case where there are zero groups to remove any that we might otherwise - inherit (as pointed out by grawity at gmail.com) and since the 2nd argument - to setgroups is always a static global it's always valid to dereference in - this case. ok deraadt@ djm@ - - Upstream-ID: 895b5ac560a10befc6b82afa778641315725fd01 - -commit 882f8bf94f79528caa65b0ba71c185d705bb7195 -Author: dtucker@openbsd.org -Date: Wed Jun 24 01:49:19 2015 +0000 - - upstream commit - - Revert previous commit. We still want to call setgroups in - the case where there are zero groups to remove any that we might otherwise - inherit (as pointed out by grawity at gmail.com) and since the 2nd argument - to setgroups is always a static global it's always valid to dereference in - this case. ok deraadt@ djm@ - - Upstream-ID: 895b5ac560a10befc6b82afa778641315725fd01 - -commit 9488538a726951e82b3a4374f3c558d72c80a89b -Author: djm@openbsd.org -Date: Mon Jun 22 23:42:16 2015 +0000 - - upstream commit - - Don't count successful partial authentication as failures - in monitor; this may have caused the monitor to refuse multiple - authentications that would otherwise have successfully completed; ok markus@ - - Upstream-ID: eb74b8e506714d0f649bd5c300f762a527af04a3 - -commit 63b78d003bd8ca111a736e6cea6333da50f5f09b -Author: dtucker@openbsd.org -Date: Mon Jun 22 12:29:57 2015 +0000 - - upstream commit - - Don't call setgroups if we have zero groups; there's no - guarantee that it won't try to deref the pointer. Based on a patch from mail - at quitesimple.org, ok djm deraadt - - Upstream-ID: 2fff85e11d7a9a387ef7fddf41fbfaf566708ab1 - -commit 5c15e22c691c79a47747bcf5490126656f97cecd -Author: Damien Miller -Date: Thu Jun 18 15:07:56 2015 +1000 - - fix syntax error - -commit 596dbca82f3f567fb3d2d69af4b4e1d3ba1e6403 -Author: jsing@openbsd.org -Date: Mon Jun 15 18:44:22 2015 +0000 - - upstream commit - - If AuthorizedPrincipalsCommand is specified, however - AuthorizedPrincipalsFile is not (or is set to "none"), authentication will - potentially fail due to key_cert_check_authority() failing to locate a - principal that matches the username, even though an authorized principal has - already been matched in the output of the subprocess. Fix this by using the - same logic to determine if pw->pw_name should be passed, as is used to - determine if a authorized principal must be matched earlier on. - - ok djm@ - - Upstream-ID: 43b42302ec846b0ea68aceb40677245391b9409d - -commit aff3e94c0d75d0d0fa84ea392b50ab04f8c57905 -Author: jsing@openbsd.org -Date: Mon Jun 15 18:42:19 2015 +0000 - - upstream commit - - Make the arguments to match_principals_command() similar - to match_principals_file(), by changing the last argument a struct - sshkey_cert * and dereferencing key->cert in the caller. - - No functional change. - - ok djm@ - - Upstream-ID: 533f99b844b21b47342b32b62e198dfffcf8651c - -commit 97e2e1596c202a4693468378b16b2353fd2d6c5e -Author: Damien Miller -Date: Wed Jun 17 14:36:54 2015 +1000 - - trivial optimisation for seccomp-bpf - - When doing arg inspection and the syscall doesn't match, skip - past the instruction that reloads the syscall into the accumulator, - since the accumulator hasn't been modified at this point. - -commit 99f33d7304893bd9fa04d227cb6e870171cded19 -Author: Damien Miller -Date: Wed Jun 17 10:50:51 2015 +1000 - - aarch64 support for seccomp-bpf sandbox - - Also resort and tidy syscall list. Based on patches by Jakub Jelen - bz#2361; ok dtucker@ - -commit 4ef702e1244633c1025ec7cfe044b9ab267097bf -Author: djm@openbsd.org -Date: Mon Jun 15 01:32:50 2015 +0000 - - upstream commit - - return failure on RSA signature error; reported by Albert S - - Upstream-ID: e61bb93dbe0349625807b0810bc213a6822121fa - -commit a170f22baf18af0b1acf2788b8b715605f41a1f9 -Author: Tim Rice -Date: Tue Jun 9 22:41:13 2015 -0700 - - Fix t12 rules for out of tree builds. - -commit ec04dc4a5515c913121bc04ed261857e68fa5c18 -Author: millert@openbsd.org -Date: Fri Jun 5 15:13:13 2015 +0000 - - upstream commit - - For "ssh -L 12345:/tmp/sock" don't fail with "No forward host - name." (we have a path, not a host name). Based on a diff from Jared - Yanovich. OK djm@ - - Upstream-ID: 2846b0a8c7de037e33657f95afbd282837fc213f - -commit 732d61f417a6aea0aa5308b59cb0f563bcd6edd6 -Author: djm@openbsd.org -Date: Fri Jun 5 03:44:14 2015 +0000 - - upstream commit - - typo: accidental repetition; bz#2386 - - Upstream-ID: 45e620d99f6bc301e5949d34a54027374991c88b - -commit adfb24c69d1b6f5e758db200866c711e25a2ba73 -Author: Darren Tucker -Date: Fri Jun 5 14:51:40 2015 +1000 - - Add Linux powerpc64le and powerpcle entries. - - Stopgap to resolve bz#2409 because we are so close to release and will - update config.guess and friends shortly after the release. ok djm@ - -commit a1195a0fdc9eddddb04d3e9e44c4775431cb77da -Merge: 6397eed d2480bc -Author: Tim Rice -Date: Wed Jun 3 21:43:13 2015 -0700 - - Merge branch 'master' of git.mindrot.org:/var/git/openssh - -commit 6397eedf953b2b973d2d7cbb504ab501a07f8ddc -Author: Tim Rice -Date: Wed Jun 3 21:41:11 2015 -0700 - - Remove unneeded backslashes. Patch from Ángel González - -commit d2480bcac1caf31b03068de877a47d6e1027bf6d -Author: Darren Tucker -Date: Thu Jun 4 14:10:55 2015 +1000 - - Remove redundant include of stdarg.h. bz#2410 - -commit 5e67859a623826ccdf2df284cbb37e2d8e2787eb -Author: djm@openbsd.org -Date: Tue Jun 2 09:10:40 2015 +0000 - - upstream commit - - mention CheckHostIP adding addresses to known_hosts; - bz#1993; ok dtucker@ - - Upstream-ID: fd44b68440fd0dc29abf9f2d3f703d74a2396cb7 - -commit d7a58bbac6583e33fd5eca8e2c2cc70c57617818 -Author: Darren Tucker -Date: Tue Jun 2 20:15:26 2015 +1000 - - Replace strcpy with strlcpy. - - ok djm, sanity check by Corinna Vinschen. - -commit 51a1c2115265c6e80ede8a5c9dccada9aeed7143 -Author: Damien Miller -Date: Fri May 29 18:27:21 2015 +1000 - - skip, rather than fatal when run without SUDO set - -commit 599f01142a376645b15cbc9349d7e8975e1cf245 -Author: Damien Miller -Date: Fri May 29 18:03:15 2015 +1000 - - fix merge botch that left ",," in KEX algs - -commit 0c2a81dfc21822f2423edd30751e5ec53467b347 -Author: Damien Miller -Date: Fri May 29 17:08:28 2015 +1000 - - re-enable SSH protocol 1 at compile time - -commit db438f9285d64282d3ac9e8c0944f59f037c0151 -Author: djm@openbsd.org -Date: Fri May 29 03:05:13 2015 +0000 - - upstream commit - - make this work without SUDO set; ok dtucker@ - - Upstream-Regress-ID: bca88217b70bce2fe52b23b8e06bdeb82d98c715 - -commit 1d9a2e2849c9864fe75daabf433436341c968e14 -Author: djm@openbsd.org -Date: Thu May 28 07:37:31 2015 +0000 - - upstream commit - - wrap all moduli-related code in #ifdef WITH_OPENSSL. - based on patch from Reuben Hawkins; bz#2388 feedback and ok dtucker@ - - Upstream-ID: d80cfc8be3e6ec65b3fac9e87c4466533b31b7cf - -commit 496aeb25bc2d6c434171292e4714771b594bd00e -Author: dtucker@openbsd.org -Date: Thu May 28 05:41:29 2015 +0000 - - upstream commit - - Increase the allowed length of the known host file name - in the log message to be consistent with other cases. Part of bz#1993, ok - deraadt. - - Upstream-ID: a9e97567be49f25daf286721450968251ff78397 - -commit dd2cfeb586c646ff8d70eb93567b2e559ace5b14 -Author: dtucker@openbsd.org -Date: Thu May 28 05:09:45 2015 +0000 - - upstream commit - - Fix typo (keywork->keyword) - - Upstream-ID: 8aacd0f4089c0a244cf43417f4f9045dfaeab534 - -commit 9cc6842493fbf23025ccc1edab064869640d3bec -Author: djm@openbsd.org -Date: Thu May 28 04:50:53 2015 +0000 - - upstream commit - - add error message on ftruncate failure; bz#2176 - - Upstream-ID: cbcc606e0b748520c74a210d8f3cc9718d3148cf - -commit d1958793a0072c22be26d136dbda5ae263e717a0 -Author: djm@openbsd.org -Date: Thu May 28 04:40:13 2015 +0000 - - upstream commit - - make ssh-keygen default to ed25519 keys when compiled - without OpenSSL; bz#2388, ok dtucker@ - - Upstream-ID: 85a471fa6d3fa57a7b8e882d22cfbfc1d84cdc71 - -commit 3ecde664c9fc5fb3667aedf9e6671462600f6496 -Author: dtucker@openbsd.org -Date: Wed May 27 23:51:10 2015 +0000 - - upstream commit - - Reorder client proposal to prefer - diffie-hellman-group-exchange-sha1 over diffie-hellman-group14-sha1. ok djm@ - - Upstream-ID: 552c08d47347c3ee1a9a57d88441ab50abe17058 - -commit 40f64292b907afd0a674fdbf3e4c2356d17a7d68 -Author: dtucker@openbsd.org -Date: Wed May 27 23:39:18 2015 +0000 - - upstream commit - - Add a stronger (4k bit) fallback group that sshd can use - when the moduli file is missing or broken, sourced from RFC3526. bz#2302, ok - markus@ (earlier version), djm@ - - Upstream-ID: b635215746a25a829d117673d5e5a76d4baee7f4 - -commit 5ab7d5fa03ad55bc438fab45dfb3aeb30a3c237a -Author: Darren Tucker -Date: Thu May 28 10:03:40 2015 +1000 - - New moduli file from OpenBSD, removing 1k groups. - - Remove 1k bit groups. ok deraadt@, markus@ - -commit a71ba58adf34e599f30cdda6e9b93ae6e3937eea -Author: djm@openbsd.org -Date: Wed May 27 05:15:02 2015 +0000 - - upstream commit - - support PKCS#11 devices with external PIN entry devices - bz#2240, based on patch from Dirk-Willem van Gulik; feedback and ok dtucker@ - - Upstream-ID: 504568992b55a8fc984375242b1bd505ced61b0d - -commit b282fec1aa05246ed3482270eb70fc3ec5f39a00 -Author: dtucker@openbsd.org -Date: Tue May 26 23:23:40 2015 +0000 - - upstream commit - - Cap DH-GEX group size at 4kbits for Cisco implementations. - Some of them will choke when asked for preferred sizes >4k instead of - returning the 4k group that they do have. bz#2209, ok djm@ - - Upstream-ID: 54b863a19713446b7431f9d06ad0532b4fcfef8d - -commit 3e91b4e8b0dc2b4b7e7d42cf6e8994a32e4cb55e -Author: djm@openbsd.org -Date: Sun May 24 23:39:16 2015 +0000 - - upstream commit - - add missing 'c' option to getopt(), case statement was - already there; from Felix Bolte - - Upstream-ID: 9b19b4e2e0b54d6fefa0dfac707c51cf4bae3081 - -commit 64a89ec07660abba4d0da7c0095b7371c98bab62 -Author: jsg@openbsd.org -Date: Sat May 23 14:28:37 2015 +0000 - - upstream commit - - fix a memory leak in an error path ok markus@ dtucker@ - - Upstream-ID: bc1da0f205494944918533d8780fde65dff6c598 - -commit f948737449257d2cb83ffcfe7275eb79b677fd4a -Author: djm@openbsd.org -Date: Fri May 22 05:28:45 2015 +0000 - - upstream commit - - mention ssh-keygen -E for comparing legacy MD5 - fingerprints; bz#2332 - - Upstream-ID: 079a3669549041dbf10dbc072d9563f0dc3b2859 - -commit 0882332616e4f0272c31cc47bf2018f9cb258a4e -Author: djm@openbsd.org -Date: Fri May 22 04:45:52 2015 +0000 - - upstream commit - - Reorder EscapeChar option parsing to avoid a single-byte - out- of-bounds read. bz#2396 from Jaak Ristioja; ok dtucker@ - - Upstream-ID: 1dc6b5b63d1c8d9a88619da0b27ade461d79b060 - -commit d7c31da4d42c115843edee2074d7d501f8804420 -Author: djm@openbsd.org -Date: Fri May 22 03:50:02 2015 +0000 - - upstream commit - - add knob to relax GSSAPI host credential check for - multihomed hosts bz#928, patch by Simon Wilkinson; ok dtucker - (kerberos/GSSAPI is not compiled by default on OpenBSD) - - Upstream-ID: 15ddf1c6f7fd9d98eea9962f480079ae3637285d - -commit aa72196a00be6e0b666215edcffbc10af234cb0e -Author: Darren Tucker -Date: Fri May 22 17:49:46 2015 +1000 - - Include signal.h for sig_atomic_t, used by kex.h. - - bz#2402, from tomas.kuthan at oracle com. - -commit 8b02481143d75e91c49d1bfae0876ac1fbf9511a -Author: Darren Tucker -Date: Fri May 22 12:47:24 2015 +1000 - - Import updated moduli file from OpenBSD. - -commit 4739e8d5e1c0be49624082bd9f6b077e9e758db9 -Author: djm@openbsd.org -Date: Thu May 21 12:01:19 2015 +0000 - - upstream commit - - Support "ssh-keygen -lF hostname" to find search known_hosts - and print key hashes. Already advertised by ssh-keygen(1), but not delivered - by code; ok dtucker@ - - Upstream-ID: 459e0e2bf39825e41b0811c336db2d56a1c23387 - -commit e97201feca10b5196da35819ae516d0b87cf3a50 -Author: Damien Miller -Date: Thu May 21 17:55:15 2015 +1000 - - conditionalise util.h inclusion - -commit 13640798c7dd011ece0a7d02841fe48e94cfa0e0 -Author: djm@openbsd.org -Date: Thu May 21 06:44:25 2015 +0000 - - upstream commit - - regress test for AuthorizedPrincipalsCommand - - Upstream-Regress-ID: c658fbf1ab6b6011dc83b73402322e396f1e1219 - -commit 84452c5d03c21f9bfb28c234e0dc1dc67dd817b1 -Author: djm@openbsd.org -Date: Thu May 21 06:40:02 2015 +0000 - - upstream commit - - regress test for AuthorizedKeysCommand arguments - - Upstream-Regress-ID: bbd65c13c6b3be9a442ec115800bff9625898f12 - -commit bcc50d816187fa9a03907ac1f3a52f04a52e10d1 -Author: djm@openbsd.org -Date: Thu May 21 06:43:30 2015 +0000 - - upstream commit - - add AuthorizedPrincipalsCommand that allows getting - authorized_principals from a subprocess rather than a file, which is quite - useful in deployments with large userbases - - feedback and ok markus@ - - Upstream-ID: aa1bdac7b16fc6d2fa3524ef08f04c7258d247f6 - -commit 24232a3e5ab467678a86aa67968bbb915caffed4 -Author: djm@openbsd.org -Date: Thu May 21 06:38:35 2015 +0000 - - upstream commit - - support arguments to AuthorizedKeysCommand - - bz#2081 loosely based on patch by Sami Hartikainen - feedback and ok markus@ - - Upstream-ID: b080387a14aa67dddd8ece67c00f268d626541f7 - -commit d80fbe41a57c72420c87a628444da16d09d66ca7 -Author: djm@openbsd.org -Date: Thu May 21 04:55:51 2015 +0000 - - upstream commit - - refactor: split base64 encoding of pubkey into its own - sshkey_to_base64() function and out of sshkey_write(); ok markus@ - - Upstream-ID: 54fc38f5832e9b91028900819bda46c3959a0c1a - -commit 7cc44ef74133a473734bbcbd3484f24d6a7328c5 -Author: deraadt@openbsd.org -Date: Mon May 18 15:06:05 2015 +0000 - - upstream commit - - getentropy() and sendsyslog() have been around long - enough. openssh-portable may want the #ifdef's but not base. discussed with - djm few weeks back - - Upstream-ID: 0506a4334de108e3fb6c66f8d6e0f9c112866926 - -commit 9173d0fbe44de7ebcad8a15618e13a8b8d78902e -Author: dtucker@openbsd.org -Date: Fri May 15 05:44:21 2015 +0000 - - upstream commit - - Use a salted hash of the lock passphrase instead of plain - text and do constant-time comparisons of it. Should prevent leaking any - information about it via timing, pointed out by Ryan Castellucci. Add a 0.1s - incrementing delay for each failed unlock attempt up to 10s. ok markus@ - (earlier version), djm@ - - Upstream-ID: c599fcc325aa1cc65496b25220b622d22208c85f - -commit d028d5d3a697c71b21e4066d8672cacab3caa0a8 -Author: Damien Miller -Date: Tue May 5 19:10:58 2015 +1000 - - upstream commit - - - tedu@cvs.openbsd.org 2015/01/12 03:20:04 - [bcrypt_pbkdf.c] - rename blocks to words. bcrypt "blocks" are unrelated to blowfish blocks, - nor are they the same size. - -commit f6391d4e59b058984163ab28f4e317e7a72478f1 -Author: Damien Miller -Date: Tue May 5 19:10:23 2015 +1000 - - upstream commit - - - deraadt@cvs.openbsd.org 2015/01/08 00:30:07 - [bcrypt_pbkdf.c] - declare a local version of MIN(), call it MINIMUM() - -commit 8ac6b13cc9113eb47cd9e86c97d7b26b4b71b77f -Author: Damien Miller -Date: Tue May 5 19:09:46 2015 +1000 - - upstream commit - - - djm@cvs.openbsd.org 2014/12/30 01:41:43 - [bcrypt_pbkdf.c] - typo in comment: ouput => output - -commit 1f792489d5cf86a4f4e3003e6e9177654033f0f2 -Author: djm@openbsd.org -Date: Mon May 4 06:10:48 2015 +0000 - - upstream commit - - Remove pattern length argument from match_pattern_list(), we - only ever use it for strlen(pattern). - - Prompted by hanno AT hboeck.de pointing an out-of-bound read - error caused by an incorrect pattern length found using AFL - and his own tools. - - ok markus@ - -commit 639d6bc57b1942393ed12fb48f00bc05d4e093e4 -Author: djm@openbsd.org -Date: Fri May 1 07:10:01 2015 +0000 - - upstream commit - - refactor ssh_dispatch_run_fatal() to use sshpkt_fatal() - to better report error conditions. Teach sshpkt_fatal() about ECONNRESET. - - Improves error messages on TCP connection resets. bz#2257 - - ok dtucker@ - -commit 9559d7de34c572d4d3fd990ca211f8ec99f62c4d -Author: djm@openbsd.org -Date: Fri May 1 07:08:08 2015 +0000 - - upstream commit - - a couple of parse targets were missing activep checks, - causing them to be misapplied in match context; bz#2272 diagnosis and - original patch from Sami Hartikainen ok dtucker@ - -commit 7e8528cad04b2775c3b7db08abf8fb42e47e6b2a -Author: djm@openbsd.org -Date: Fri May 1 04:17:51 2015 +0000 - - upstream commit - - make handling of AuthorizedPrincipalsFile=none more - consistent with other =none options; bz#2288 from Jakub Jelen; ok dtucker@ - -commit ca430d4d9cc0f62eca3b1fb1e2928395b7ce80f7 -Author: djm@openbsd.org -Date: Fri May 1 04:03:20 2015 +0000 - - upstream commit - - remove failed remote forwards established by muliplexing - from the list of active forwards; bz#2363, patch mostly by Yoann Ricordel; ok - dtucker@ - -commit 8312cfb8ad88657517b3e23ac8c56c8e38eb9792 -Author: djm@openbsd.org -Date: Fri May 1 04:01:58 2015 +0000 - - upstream commit - - reduce stderr spam when using ssh -S /path/mux -O forward - -R 0:... ok dtucker@ - -commit 179be0f5e62f1f492462571944e45a3da660d82b -Author: djm@openbsd.org -Date: Fri May 1 03:23:51 2015 +0000 - - upstream commit - - prevent authorized_keys options picked up on public key - tests without a corresponding private key authentication being applied to - other authentication methods. Reported by halex@, ok markus@ - -commit a42d67be65b719a430b7fcaba2a4e4118382723a -Author: djm@openbsd.org -Date: Fri May 1 03:20:54 2015 +0000 - - upstream commit - - Don't make parsing of authorized_keys' environment= - option conditional on PermitUserEnv - always parse it, but only use the - result if the option is enabled. This prevents the syntax of authorized_keys - changing depending on which sshd_config options were enabled. - - bz#2329; based on patch from coladict AT gmail.com, ok dtucker@ - -commit e661a86353e11592c7ed6a847e19a83609f49e77 -Author: djm@openbsd.org -Date: Mon May 4 06:10:48 2015 +0000 - - upstream commit - - Remove pattern length argument from match_pattern_list(), we - only ever use it for strlen(pattern). - - Prompted by hanno AT hboeck.de pointing an out-of-bound read - error caused by an incorrect pattern length found using AFL - and his own tools. - - ok markus@ - -commit 0ef1de742be2ee4b10381193fe90730925b7f027 -Author: dtucker@openbsd.org -Date: Thu Apr 23 05:01:19 2015 +0000 - - upstream commit - - Add a simple regression test for sshd's configuration - parser. Right now, all it does is run the output of sshd -T back through - itself and ensure the output is valid and invariant. - -commit 368f83c793275faa2c52f60eaa9bdac155c4254b -Author: djm@openbsd.org -Date: Wed Apr 22 01:38:36 2015 +0000 - - upstream commit - - use correct key for nested certificate test - -commit 8d4d1bfddbbd7d21f545dc6997081d1ea1fbc99a -Author: djm@openbsd.org -Date: Fri May 1 07:11:47 2015 +0000 - - upstream commit - - mention that the user's shell from /etc/passwd is used - for commands too; bz#1459 ok dtucker@ - -commit 5ab283d0016bbc9d4d71e8e5284d011bc5a930cf -Author: djm@openbsd.org -Date: Fri May 8 07:29:00 2015 +0000 - - upstream commit - - whitespace - - Upstream-Regress-ID: 6b708a3e709d5b7fd37890f874bafdff1f597519 - -commit 8377d5008ad260048192e1e56ad7d15a56d103dd -Author: djm@openbsd.org -Date: Fri May 8 07:26:13 2015 +0000 - - upstream commit - - whitespace at EOL - - Upstream-Regress-ID: 9c48911643d5b05173b36a012041bed4080b8554 - -commit c28a3436fa8737709ea88e4437f8f23a6ab50359 -Author: djm@openbsd.org -Date: Fri May 8 06:45:13 2015 +0000 - - upstream commit - - moar whitespace at eol - - Upstream-ID: 64eaf872a3ba52ed41e494287e80d40aaba4b515 - -commit 2b64c490468fd4ca35ac8d5cc31c0520dc1508bb -Author: djm@openbsd.org -Date: Fri May 8 06:41:56 2015 +0000 - - upstream commit - - whitespace at EOL - - Upstream-ID: 57bcf67d666c6fc1ad798aee448fdc3f70f7ec2c - -commit 4e636cf201ce6e7e3b9088568218f9d4e2c51712 -Author: djm@openbsd.org -Date: Fri May 8 03:56:51 2015 +0000 - - upstream commit - - whitespace at EOL - -commit 38b8272f823dc1dd4e29dbcee83943ed48bb12fa -Author: dtucker@openbsd.org -Date: Mon May 4 01:47:53 2015 +0000 - - upstream commit - - Use diff w/out -u for better portability - -commit 297060f42d5189a4065ea1b6f0afdf6371fb0507 -Author: dtucker@openbsd.org -Date: Fri May 8 03:25:07 2015 +0000 - - upstream commit - - Use xcalloc for permitted_adm_opens instead of xmalloc to - ensure it's zeroed. Fixes post-auth crash with permitopen=none. bz#2355, ok - djm@ - -commit 63ebf019be863b2d90492a85e248cf55a6e87403 -Author: djm@openbsd.org -Date: Fri May 8 03:17:49 2015 +0000 - - upstream commit - - don't choke on new-format private keys encrypted with an - AEAD cipher; bz#2366, patch from Ron Frederick; ok markus@ - -commit f8484dac678ab3098ae522a5f03bb2530f822987 -Author: dtucker@openbsd.org -Date: Wed May 6 05:45:17 2015 +0000 - - upstream commit - - Clarify pseudo-terminal request behaviour and use - "pseudo-terminal" consistently. bz#1716, ok jmc@ "I like it" deraadt@. - -commit ea139507bef8bad26e86ed99a42c7233ad115c38 -Author: dtucker@openbsd.org -Date: Wed May 6 04:07:18 2015 +0000 - - upstream commit - - Blacklist DH-GEX for specific PuTTY versions known to - send non-RFC4419 DH-GEX messages rather than all versions of PuTTY. - According to Simon Tatham, 0.65 and newer versions will send RFC4419 DH-GEX - messages. ok djm@ - -commit b58234f00ee3872eb84f6e9e572a9a34e902e36e -Author: dtucker@openbsd.org -Date: Tue May 5 10:17:49 2015 +0000 - - upstream commit - - WinSCP doesn't implement RFC4419 DH-GEX so flag it so we - don't offer that KEX method. ok markus@ - -commit d5b1507a207253b39e810e91e68f9598691b7a29 -Author: jsg@openbsd.org -Date: Tue May 5 02:48:17 2015 +0000 - - upstream commit - - use the sizeof the struct not the sizeof a pointer to the - struct in ssh_digest_start() - - This file is only used if ssh is built with OPENSSL=no - - ok markus@ - -commit a647b9b8e616c231594b2710c925d31b1b8afea3 -Author: Darren Tucker -Date: Fri May 8 11:07:27 2015 +1000 - - Put brackets around mblen() compat constant. - - This might help with the reported problem cross compiling for Android - ("error: expected identifier or '(' before numeric constant") but - shouldn't hurt in any case. - -commit d1680d36e17244d9af3843aeb5025cb8e40d6c07 -Author: Darren Tucker -Date: Thu Apr 30 09:18:11 2015 +1000 - - xrealloc -> xreallocarray in portable code too. - -commit 531a57a3893f9fcd4aaaba8c312b612bbbcc021e -Author: dtucker@openbsd.org -Date: Wed Apr 29 03:48:56 2015 +0000 - - upstream commit - - Allow ListenAddress, Port and AddressFamily in any - order. bz#68, ok djm@, jmc@ (for the man page bit). - -commit c1d5bcf1aaf1209af02f79e48ba1cbc76a87b56f -Author: jmc@openbsd.org -Date: Tue Apr 28 13:47:38 2015 +0000 - - upstream commit - - enviroment -> environment: apologies to darren for not - spotting that first time round... - -commit 43beea053db191cac47c2cd8d3dc1930158aff1a -Author: dtucker@openbsd.org -Date: Tue Apr 28 10:25:15 2015 +0000 - - upstream commit - - Fix typo in previous - -commit 85b96ef41374f3ddc9139581f87da09b2cd9199e -Author: dtucker@openbsd.org -Date: Tue Apr 28 10:17:58 2015 +0000 - - upstream commit - - Document that the TERM environment variable is not - subject to SendEnv and AcceptEnv. bz#2386, based loosely on a patch from - jjelen at redhat, help and ok jmc@ - -commit 88a7c598a94ff53f76df228eeaae238d2d467565 -Author: djm@openbsd.org -Date: Mon Apr 27 21:42:48 2015 +0000 - - upstream commit - - Make sshd default to PermitRootLogin=no; ok deraadt@ - rpe@ - -commit 734226b4480a6c736096c729fcf6f391400599c7 -Author: djm@openbsd.org -Date: Mon Apr 27 01:52:30 2015 +0000 - - upstream commit - - fix compilation with OPENSSL=no; ok dtucker@ - -commit a4b9d2ce1eb7703eaf0809b0c8a82ded8aa4f1c6 -Author: dtucker@openbsd.org -Date: Mon Apr 27 00:37:53 2015 +0000 - - upstream commit - - Include stdio.h for FILE (used in sshkey.h) so it - compiles with OPENSSL=no. - -commit dbcc652f4ca11fe04e5930c7ef18a219318c6cda -Author: djm@openbsd.org -Date: Mon Apr 27 00:21:21 2015 +0000 - - upstream commit - - allow "sshd -f none" to skip reading the config file, - much like "ssh -F none" does. ok dtucker - -commit b7ca276fca316c952f0b90f5adb1448c8481eedc -Author: jmc@openbsd.org -Date: Fri Apr 24 06:26:49 2015 +0000 - - upstream commit - - combine -Dd onto one line and update usage(); - -commit 2ea974630d7017e4c7666d14d9dc939707613e96 -Author: djm@openbsd.org -Date: Fri Apr 24 05:26:44 2015 +0000 - - upstream commit - - add ssh-agent -D to leave ssh-agent in foreground - without enabling debug mode; bz#2381 ok dtucker@ - -commit 8ac2ffd7aa06042f6b924c87139f2fea5c5682f7 -Author: deraadt@openbsd.org -Date: Fri Apr 24 01:36:24 2015 +0000 - - upstream commit - - 2*len -> use xreallocarray() ok djm - -commit 657a5fbc0d0aff309079ff8fb386f17e964963c2 -Author: deraadt@openbsd.org -Date: Fri Apr 24 01:36:00 2015 +0000 - - upstream commit - - rename xrealloc() to xreallocarray() since it follows - that form. ok djm - -commit 1108ae242fdd2c304307b68ddf46aebe43ebffaa -Author: dtucker@openbsd.org -Date: Thu Apr 23 04:59:10 2015 +0000 - - upstream commit - - Two small fixes for sshd -T: ListenAddress'es are added - to a list head so reverse the order when printing them to ensure the - behaviour remains the same, and print StreamLocalBindMask as octal with - leading zero. ok deraadt@ - -commit bd902b8473e1168f19378d5d0ae68d0c203525df -Author: dtucker@openbsd.org -Date: Thu Apr 23 04:53:53 2015 +0000 - - upstream commit - - Check for and reject missing arguments for - VersionAddendum and ForceCommand. bz#2281, patch from plautrba at redhat com, - ok djm@ - -commit ca42c1758575e592239de1d5755140e054b91a0d -Author: djm@openbsd.org -Date: Wed Apr 22 01:24:01 2015 +0000 - - upstream commit - - unknown certificate extensions are non-fatal, so don't - fatal when they are encountered; bz#2387 reported by Bob Van Zant; ok - dtucker@ - -commit 39bfbf7caad231cc4bda6909fb1af0705bca04d8 -Author: jsg@openbsd.org -Date: Tue Apr 21 07:01:00 2015 +0000 - - upstream commit - - Add back a backslash removed in rev 1.42 so - KEX_SERVER_ENCRYPT will include aes again. - - ok deraadt@ - -commit 6b0d576bb87eca3efd2b309fcfe4edfefc289f9c -Author: djm@openbsd.org -Date: Fri Apr 17 13:32:09 2015 +0000 - - upstream commit - - s/recommended/required/ that private keys be og-r this - wording change was made a while ago but got accidentally reverted - -commit 44a8e7ce6f3ab4c2eb1ae49115c210b98e53c4df -Author: djm@openbsd.org -Date: Fri Apr 17 13:25:52 2015 +0000 - - upstream commit - - don't try to cleanup NULL KEX proposals in - kex_prop_free(); found by Jukka Taimisto and Markus Hietava - -commit 3038a191872d2882052306098c1810d14835e704 -Author: djm@openbsd.org -Date: Fri Apr 17 13:19:22 2015 +0000 - - upstream commit - - use error/logit/fatal instead of fprintf(stderr, ...) - and exit(0), fix a few errors that were being printed to stdout instead of - stderr and a few non-errors that were going to stderr instead of stdout - bz#2325; ok dtucker - -commit a58be33cb6cd24441fa7e634db0e5babdd56f07f -Author: djm@openbsd.org -Date: Fri Apr 17 13:16:48 2015 +0000 - - upstream commit - - debug log missing DISPLAY environment when X11 - forwarding requested; bz#1682 ok dtucker@ - -commit 17d4d9d9fbc8fb80e322f94d95eecc604588a474 -Author: djm@openbsd.org -Date: Fri Apr 17 04:32:31 2015 +0000 - - upstream commit - - don't call record_login() in monitor when UseLogin is - enabled; bz#278 reported by drk AT sgi.com; ok dtucker - -commit 40132ff87b6cbc3dc05fb5df2e9d8e3afa06aafd -Author: dtucker@openbsd.org -Date: Fri Apr 17 04:12:35 2015 +0000 - - upstream commit - - Add some missing options to sshd -T and fix the output - of VersionAddendum HostCertificate. bz#2346, patch from jjelen at redhat - com, ok djm. - -commit 6cc7cfa936afde2d829e56ee6528c7ea47a42441 -Author: dtucker@openbsd.org -Date: Thu Apr 16 23:25:50 2015 +0000 - - upstream commit - - Document "none" for PidFile XAuthLocation - TrustedUserCAKeys and RevokedKeys. bz#2382, feedback from jmc@, ok djm@ - -commit 15fdfc9b1c6808b26bc54d4d61a38b54541763ed -Author: dtucker@openbsd.org -Date: Wed Apr 15 23:23:25 2015 +0000 - - upstream commit - - Plug leak of address passed to logging. bz#2373, patch - from jjelen at redhat, ok markus@ - -commit bb2289e2a47d465eaaaeff3dee2a6b7777b4c291 -Author: dtucker@openbsd.org -Date: Tue Apr 14 04:17:03 2015 +0000 - - upstream commit - - Output remote username in debug output since with Host - and Match it's not always obvious what it will be. bz#2368, ok djm@ - -commit 70860b6d07461906730632f9758ff1b7c98c695a -Author: Darren Tucker -Date: Fri Apr 17 10:56:13 2015 +1000 - - Format UsePAM setting when using sshd -T. - - Part of bz#2346, patch from jjelen at redhat com. - -commit ee15d9c9f0720f5a8b0b34e4b10ecf21f9824814 -Author: Darren Tucker -Date: Fri Apr 17 10:40:23 2015 +1000 - - Wrap endian.h include inside ifdef (bz#2370). - -commit 408f4c2ad4a4c41baa7b9b2b7423d875abbfa70b -Author: Darren Tucker -Date: Fri Apr 17 09:39:58 2015 +1000 - - Look for '${host}-ar' before 'ar'. - - This changes configure.ac to look for '${host}-ar' as set by - AC_CANONICAL_HOST before looking for the unprefixed 'ar'. - Useful when cross-compiling when all your binutils are prefixed. - - Patch from moben at exherbo org via astrand at lysator liu se and - bz#2352. - -commit 673a1c16ad078d41558247ce739fe812c960acc8 -Author: Damien Miller -Date: Thu Apr 16 11:40:20 2015 +1000 - - remove dependency on arpa/telnet.h - -commit 202d443eeda1829d336595a3cfc07827e49f45ed -Author: Darren Tucker -Date: Wed Apr 15 15:59:49 2015 +1000 - - Remove duplicate include of pwd.h. bz#2337, patch from Mordy Ovits. - -commit 597986493412c499f2bc2209420cb195f97b3668 -Author: Damien Miller -Date: Thu Apr 9 10:14:48 2015 +1000 - - platform's with openpty don't need pty_release - -commit 318be28cda1fd9108f2e6f2f86b0b7589ba2aed0 -Author: djm@openbsd.org -Date: Mon Apr 13 02:04:08 2015 +0000 - - upstream commit - - deprecate ancient, pre-RFC4419 and undocumented - SSH2_MSG_KEX_DH_GEX_REQUEST_OLD message; ok markus@ deraadt@ "seems - reasonable" dtucker@ - -commit d8f391caef62378463a0e6b36f940170dadfe605 -Author: dtucker@openbsd.org -Date: Fri Apr 10 05:16:50 2015 +0000 - - upstream commit - - Don't send hostkey advertisments - (hostkeys-00@openssh.com) to current versions of Tera Term as they can't - handle them. Newer versions should be OK. Patch from Bryan Drewery and - IWAMOTO Kouichi, ok djm@ - -commit 2c2cfe1a1c97eb9a08cc9817fd0678209680c636 -Author: djm@openbsd.org -Date: Fri Apr 10 00:08:55 2015 +0000 - - upstream commit - - include port number if a non-default one has been - specified; based on patch from Michael Handler - -commit 4492a4f222da4cf1e8eab12689196322e27b08c4 -Author: djm@openbsd.org -Date: Tue Apr 7 23:00:42 2015 +0000 - - upstream commit - - treat Protocol=1,2|2,1 as Protocol=2 when compiled - without SSH1 support; ok dtucker@ millert@ - -commit c265e2e6e932efc6d86f6cc885dea33637a67564 -Author: miod@openbsd.org -Date: Sun Apr 5 15:43:43 2015 +0000 - - upstream commit - - Do not use int for sig_atomic_t; spotted by - christos@netbsd; ok markus@ - -commit e7bf3a5eda6a1b02bef6096fed78527ee11e54cc -Author: Darren Tucker -Date: Tue Apr 7 10:48:04 2015 +1000 - - Use do{}while(0) for no-op functions. - - From FreeBSD. - -commit bb99844abae2b6447272f79e7fa84134802eb4df -Author: Darren Tucker -Date: Tue Apr 7 10:47:15 2015 +1000 - - Wrap blf.h include in ifdef. From FreeBSD. - -commit d9b9b43656091cf0ad55c122f08fadb07dad0abd -Author: Darren Tucker -Date: Tue Apr 7 09:10:00 2015 +1000 - - Fix misspellings of regress CONFOPTS env variables. - - Patch from Bryan Drewery. - -commit 3f4ea3c9ab1d32d43c9222c4351f58ca11144156 -Author: djm@openbsd.org -Date: Fri Apr 3 22:17:27 2015 +0000 - - upstream commit - - correct return value in pubkey parsing, spotted by Ben Hawkes - ok markus@ - -commit 7da2be0cb9601ed25460c83aa4d44052b967ba0f -Author: djm@openbsd.org -Date: Tue Mar 31 22:59:01 2015 +0000 - - upstream commit - - adapt to recent hostfile.c change: when parsing - known_hosts without fully parsing the keys therein, hostkeys_foreach() will - now correctly identify KEY_RSA1 keys; ok markus@ miod@ - -commit 9e1777a0d1c706714b055811c12ab8cc21033e4a -Author: markus@openbsd.org -Date: Tue Mar 24 20:19:15 2015 +0000 - - upstream commit - - use ${SSH} for -Q instead of installed ssh - -commit ce1b358ea414a2cc88e4430cd5a2ea7fecd9de57 -Author: djm@openbsd.org -Date: Mon Mar 16 22:46:14 2015 +0000 - - upstream commit - - make CLEANFILES clean up more of the tests' droppings - -commit 398f9ef192d820b67beba01ec234d66faca65775 -Author: djm@openbsd.org -Date: Tue Mar 31 22:57:06 2015 +0000 - - upstream commit - - downgrade error() for known_hosts parse errors to debug() - to quiet warnings from ssh1 keys present when compiled !ssh1. - - also identify ssh1 keys when scanning, even when compiled !ssh1 - - ok markus@ miod@ - -commit 9a47ab80030a31f2d122b8fd95bd48c408b9fcd9 -Author: djm@openbsd.org -Date: Tue Mar 31 22:55:50 2015 +0000 - - upstream commit - - fd leak for !ssh1 case; found by unittests; ok markus@ - -commit c9a0805a6280681901c270755a7cd630d7c5280e -Author: djm@openbsd.org -Date: Tue Mar 31 22:55:24 2015 +0000 - - upstream commit - - don't fatal when a !ssh1 sshd is reexeced from a w/ssh1 - listener; reported by miod@; ok miod@ markus@ - -commit 704d8c88988cae38fb755a6243b119731d223222 -Author: tobias@openbsd.org -Date: Tue Mar 31 11:06:49 2015 +0000 - - upstream commit - - Comments are only supported for RSA1 keys. If a user - tried to add one and entered his passphrase, explicitly clear it before exit. - This is done in all other error paths, too. - - ok djm - -commit 78de1673c05ea2c33e0d4a4b64ecb5186b6ea2e9 -Author: jmc@openbsd.org -Date: Mon Mar 30 18:28:37 2015 +0000 - - upstream commit - - ssh-askpass(1) is the default, overridden by SSH_ASKPASS; - diff originally from jiri b; - -commit 26e0bcf766fadb4a44fb6199386fb1dcab65ad00 -Author: djm@openbsd.org -Date: Mon Mar 30 00:00:29 2015 +0000 - - upstream commit - - fix uninitialised memory read when parsing a config file - consisting of a single nul byte. Found by hanno AT hboeck.de using AFL; ok - dtucker - -commit fecede00a76fbb33a349f5121c0b2f9fbc04a777 -Author: markus@openbsd.org -Date: Thu Mar 26 19:32:19 2015 +0000 - - upstream commit - - sigp and lenp are not optional in ssh_agent_sign(); ok - djm@ - -commit 1b0ef3813244c78669e6d4d54c624f600945327d -Author: naddy@openbsd.org -Date: Thu Mar 26 12:32:38 2015 +0000 - - upstream commit - - don't try to load .ssh/identity by default if SSH1 is - disabled; ok markus@ - -commit f9b78852379b74a2d14e6fc94fe52af30b7e9c31 -Author: djm@openbsd.org -Date: Thu Mar 26 07:00:04 2015 +0000 - - upstream commit - - ban all-zero curve25519 keys as recommended by latest - CFRG curves draft; ok markus - -commit b8afbe2c1aaf573565e4da775261dfafc8b1ba9c -Author: djm@openbsd.org -Date: Thu Mar 26 06:59:28 2015 +0000 - - upstream commit - - relax bits needed check to allow - diffie-hellman-group1-sha1 key exchange to complete for chacha20-poly1305 was - selected as symmetric cipher; ok markus - -commit 47842f71e31da130555353c1d57a1e5a8937f1c0 -Author: markus@openbsd.org -Date: Wed Mar 25 19:29:58 2015 +0000 - - upstream commit - - ignore v1 errors on ssh-add -D; only try v2 keys on - -l/-L (unless WITH_SSH1) ok djm@ - -commit 5f57e77f91bf2230c09eca96eb5ecec39e5f2da6 -Author: markus@openbsd.org -Date: Wed Mar 25 19:21:48 2015 +0000 - - upstream commit - - unbreak ssh_agent_sign (lenp vs *lenp) - -commit 4daeb67181054f2a377677fac919ee8f9ed3490e -Author: markus@openbsd.org -Date: Tue Mar 24 20:10:08 2015 +0000 - - upstream commit - - don't leak 'setp' on error; noted by Nicholas Lemonias; - ok djm@ - -commit 7d4f96f9de2a18af0d9fa75ea89a4990de0344f5 -Author: markus@openbsd.org -Date: Tue Mar 24 20:09:11 2015 +0000 - - upstream commit - - consistent check for NULL as noted by Nicholas - Lemonias; ok djm@ - -commit df100be51354e447d9345cf1ec22e6013c0eed50 -Author: markus@openbsd.org -Date: Tue Mar 24 20:03:44 2015 +0000 - - upstream commit - - correct fmt-string for size_t as noted by Nicholas - Lemonias; ok djm@ - -commit a22b9ef21285e81775732436f7c84a27bd3f71e0 -Author: djm@openbsd.org -Date: Tue Mar 24 09:17:21 2015 +0000 - - upstream commit - - promote chacha20-poly1305@openssh.com to be the default - cipher; ok markus - -commit 2aa9da1a3b360cf7b13e96fe1521534b91501fb5 -Author: djm@openbsd.org -Date: Tue Mar 24 01:29:19 2015 +0000 - - upstream commit - - Compile-time disable SSH protocol 1. You can turn it - back on using the Makefile.inc knob if you need it to talk to ancient - devices. - -commit 53097b2022154edf96b4e8526af5666f979503f7 -Author: djm@openbsd.org -Date: Tue Mar 24 01:11:12 2015 +0000 - - upstream commit - - fix double-negative error message "ssh1 is not - unsupported" - -commit 5c27e3b6ec2db711dfcd40e6359c0bcdd0b62ea9 -Author: djm@openbsd.org -Date: Mon Mar 23 06:06:38 2015 +0000 - - upstream commit - - for ssh-keygen -A, don't try (and fail) to generate ssh - v.1 keys when compiled without SSH1 support RSA/DSA/ECDSA keys when compiled - without OpenSSL based on patch by Mike Frysinger; bz#2369 - -commit 725fd22a8c41db7de73a638539a5157b7e4424ae -Author: djm@openbsd.org -Date: Wed Mar 18 01:44:21 2015 +0000 - - upstream commit - - KRL support doesn't need OpenSSL anymore, remove #ifdefs - from around call - -commit b07011c18e0b2e172c5fd09d21fb159a0bf5fcc7 -Author: djm@openbsd.org -Date: Mon Mar 16 11:09:52 2015 +0000 - - upstream commit - - #if 0 some more arrays used only for decrypting (we don't - use since we only need encrypt for AES-CTR) - -commit 1cb3016635898d287e9d58b50c430995652d5358 -Author: jsg@openbsd.org -Date: Wed Mar 11 00:48:39 2015 +0000 - - upstream commit - - add back the changes from rev 1.206, djm reverted this by - mistake in rev 1.207 diff --git a/INSTALL b/INSTALL index 92106bf02183..e4865bbb4d9a 100644 --- a/INSTALL +++ b/INSTALL @@ -99,7 +99,7 @@ http://www.gnu.org/software/autoconf/ Basic Security Module (BSM): -Native BSM support is know to exist in Solaris from at least 2.5.1, +Native BSM support is known to exist in Solaris from at least 2.5.1, FreeBSD 6.1 and OS X. Alternatively, you may use the OpenBSM implementation (http://www.openbsm.org). diff --git a/LICENCE b/LICENCE index f52387139da7..15248212a80d 100644 --- a/LICENCE +++ b/LICENCE @@ -75,27 +75,6 @@ OpenSSH contains no GPL code. PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -2) - The 32-bit CRC compensation attack detector in deattack.c was - contributed by CORE SDI S.A. under a BSD-style license. - - * Cryptographic attack detector for ssh - source code - * - * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina. - * - * All rights reserved. Redistribution and use in source and binary - * forms, with or without modification, are permitted provided that - * this copyright notice is retained. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR - * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS - * SOFTWARE. - * - * Ariel Futoransky - * - 3) ssh-keyscan was contributed by David Mazieres under a BSD-style license. @@ -337,4 +316,4 @@ OpenSSH contains no GPL code. ------ -$OpenBSD: LICENCE,v 1.19 2004/08/30 09:18:08 markus Exp $ +$OpenBSD: LICENCE,v 1.20 2017/04/30 23:26:16 djm Exp $ diff --git a/Makefile.in b/Makefile.in index 5870e9e6e6b9..c52ce191fe95 100644 --- a/Makefile.in +++ b/Makefile.in @@ -78,10 +78,10 @@ LIBOPENSSH_OBJS=\ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ authfd.o authfile.o bufaux.o bufbn.o bufec.o buffer.o \ canohost.o channels.o cipher.o cipher-aes.o cipher-aesctr.o \ - cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \ - compat.o crc32.o deattack.o fatal.o hostfile.o \ - log.o match.o md-sha256.o moduli.o nchan.o packet.o opacket.o \ - readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \ + cipher-ctr.o cleanup.o \ + compat.o crc32.o fatal.o hostfile.o \ + log.o match.o moduli.o nchan.o packet.o opacket.o \ + readpass.o ttymodes.o xmalloc.o addrmatch.o \ atomicio.o key.o dispatch.o mac.o uidswap.o uuencode.o misc.o utf8.o \ monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ @@ -92,10 +92,10 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \ kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \ - platform-pledge.o platform-tracing.o + platform-pledge.o platform-tracing.o platform-misc.o SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect1.o sshconnect2.o mux.o + sshconnect.o sshconnect2.o mux.o SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ audit.o audit-bsm.o audit-linux.o platform.o \ @@ -228,26 +228,27 @@ umac128.o: umac.c clean: regressclean rm -f *.o *.a $(TARGETS) logintest config.cache config.log rm -f *.out core survey + rm -f regress/check-perm$(EXEEXT) rm -f regress/unittests/test_helper/*.a rm -f regress/unittests/test_helper/*.o rm -f regress/unittests/sshbuf/*.o - rm -f regress/unittests/sshbuf/test_sshbuf + rm -f regress/unittests/sshbuf/test_sshbuf$(EXEEXT) rm -f regress/unittests/sshkey/*.o - rm -f regress/unittests/sshkey/test_sshkey + rm -f regress/unittests/sshkey/test_sshkey$(EXEEXT) rm -f regress/unittests/bitmap/*.o - rm -f regress/unittests/bitmap/test_bitmap + rm -f regress/unittests/bitmap/test_bitmap$(EXEEXT) rm -f regress/unittests/conversion/*.o - rm -f regress/unittests/conversion/test_conversion + rm -f regress/unittests/conversion/test_conversion$(EXEEXT) rm -f regress/unittests/hostkeys/*.o - rm -f regress/unittests/hostkeys/test_hostkeys + rm -f regress/unittests/hostkeys/test_hostkeys$(EXEEXT) rm -f regress/unittests/kex/*.o - rm -f regress/unittests/kex/test_kex + rm -f regress/unittests/kex/test_kex$(EXEEXT) rm -f regress/unittests/match/*.o - rm -f regress/unittests/match/test_match + rm -f regress/unittests/match/test_match$(EXEEXT) rm -f regress/unittests/utf8/*.o - rm -f regress/unittests/utf8/test_utf8 + rm -f regress/unittests/utf8/test_utf8$(EXEEXT) rm -f regress/misc/kexfuzz/*.o - rm -f regress/misc/kexfuzz/kexfuzz + rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT) (cd openbsd-compat && $(MAKE) clean) distclean: regressclean diff --git a/PROTOCOL b/PROTOCOL index 192da55b2c01..4e9e8757566f 100644 --- a/PROTOCOL +++ b/PROTOCOL @@ -33,8 +33,8 @@ The method is documented in: https://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt -1.3. transport: New public key algorithms "ssh-rsa-cert-v00@openssh.com", - "ssh-dsa-cert-v00@openssh.com", +1.3. transport: New public key algorithms "ssh-rsa-cert-v01@openssh.com", + "ssh-dsa-cert-v01@openssh.com", "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ecdsa-sha2-nistp384-cert-v01@openssh.com" and "ecdsa-sha2-nistp521-cert-v01@openssh.com" @@ -454,4 +454,4 @@ respond with a SSH_FXP_STATUS message. This extension is advertised in the SSH_FXP_VERSION hello with version "1". -$OpenBSD: PROTOCOL,v 1.30 2016/04/08 06:35:54 djm Exp $ +$OpenBSD: PROTOCOL,v 1.31 2017/05/26 01:40:07 djm Exp $ diff --git a/PROTOCOL.agent b/PROTOCOL.agent index 60d36f912c68..da3381942e08 100644 --- a/PROTOCOL.agent +++ b/PROTOCOL.agent @@ -1,582 +1,5 @@ -This describes the protocol used by OpenSSH's ssh-agent. +This file used to contain a description of the SSH agent protocol +implemented by OpenSSH. It has since been superseded by an Internet- +draft that is available from: -OpenSSH's agent supports managing keys for the standard SSH protocol -2 as well as the legacy SSH protocol 1. Support for these key types -is almost completely disjoint - in all but a few cases, operations on -protocol 2 keys cannot see or affect protocol 1 keys and vice-versa. - -Protocol 1 and protocol 2 keys are separated because of the differing -cryptographic usage: protocol 1 private RSA keys are used to decrypt -challenges that were encrypted with the corresponding public key, -whereas protocol 2 RSA private keys are used to sign challenges with -a private key for verification with the corresponding public key. It -is considered unsound practice to use the same key for signing and -encryption. - -With a couple of exceptions, the protocol message names used in this -document indicate which type of key the message relates to. SSH_* -messages refer to protocol 1 keys only. SSH2_* messages refer to -protocol 2 keys. Furthermore, the names also indicate whether the -message is a request to the agent (*_AGENTC_*) or a reply from the -agent (*_AGENT_*). Section 3 below contains the mapping of the -protocol message names to their integer values. - -1. Data types - -Because of support for legacy SSH protocol 1 keys, OpenSSH's agent -protocol makes use of some data types not defined in RFC 4251. - -1.1 uint16 - -The "uint16" data type is a simple MSB-first 16 bit unsigned integer -encoded in two bytes. - -1.2 mpint1 - -The "mpint1" type represents an arbitrary precision integer (bignum). -Its format is as follows: - - uint16 bits - byte[(bits + 7) / 8] bignum - -"bignum" contains an unsigned arbitrary precision integer encoded as -eight bits per byte in big-endian (MSB first) format. - -Note the difference between the "mpint1" encoding and the "mpint" -encoding defined in RFC 4251. Also note that the length of the encoded -integer is specified in bits, not bytes and that the byte length of -the integer must be calculated by rounding up the number of bits to the -nearest eight. - -2. Protocol Messages - -All protocol messages are prefixed with their length in bytes, encoded -as a 32 bit unsigned integer. Specifically: - - uint32 message_length - byte[message_length] message - -The following message descriptions refer only to the content the -"message" field. - -2.1 Generic server responses - -The following generic messages may be sent by the server in response to -requests from the client. On success the agent may reply either with: - - byte SSH_AGENT_SUCCESS - -or a request-specific success message. - -On failure, the agent may reply with: - - byte SSH_AGENT_FAILURE - -SSH_AGENT_FAILURE messages are also sent in reply to unknown request -types. - -2.2 Adding keys to the agent - -Keys are added to the agent using the SSH_AGENTC_ADD_RSA_IDENTITY and -SSH2_AGENTC_ADD_IDENTITY requests for protocol 1 and protocol 2 keys -respectively. - -Two variants of these requests are SSH_AGENTC_ADD_RSA_ID_CONSTRAINED -and SSH2_AGENTC_ADD_ID_CONSTRAINED - these add keys with optional -"constraints" on their usage. - -OpenSSH may be built with support for keys hosted on a smartcard -or other hardware security module. These keys may be added -to the agent using the SSH_AGENTC_ADD_SMARTCARD_KEY and -SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED requests. - -2.2.1 Key constraints - -The OpenSSH agent supports some basic optional constraints on key usage. -At present there are two constraints defined. - -The first constraint limits the validity duration of a key. It is -encoded as: - - byte SSH_AGENT_CONSTRAIN_LIFETIME - uint32 seconds - -Where "seconds" contains the number of seconds that the key shall remain -valid measured from the moment that the agent receives it. After the -validity period has expired, OpenSSH's agent will erase these keys from -memory. - -The second constraint requires the agent to seek explicit user -confirmation before performing private key operations with the loaded -key. This constraint is encoded as: - - byte SSH_AGENT_CONSTRAIN_CONFIRM - -Zero or more constraints may be specified when adding a key with one -of the *_CONSTRAINED requests. Multiple constraints are appended -consecutively to the end of the request: - - byte constraint1_type - .... constraint1_data - byte constraint2_type - .... constraint2_data - .... - byte constraintN_type - .... constraintN_data - -Such a sequence of zero or more constraints will be referred to below -as "constraint[]". Agents may determine whether there are constraints -by checking whether additional data exists in the "add key" request -after the key data itself. OpenSSH will refuse to add a key if it -contains unknown constraints. - -2.2.2 Add protocol 1 key - -A client may add a protocol 1 key to an agent with the following -request: - - byte SSH_AGENTC_ADD_RSA_IDENTITY or - SSH_AGENTC_ADD_RSA_ID_CONSTRAINED - uint32 ignored - mpint1 rsa_n - mpint1 rsa_e - mpint1 rsa_d - mpint1 rsa_iqmp - mpint1 rsa_q - mpint1 rsa_p - string key_comment - constraint[] key_constraints - -Note that there is some redundancy in the key parameters; a key could be -fully specified using just rsa_q, rsa_p and rsa_e at the cost of extra -computation. - -"key_constraints" may only be present if the request type is -SSH_AGENTC_ADD_RSA_ID_CONSTRAINED. - -The agent will reply with a SSH_AGENT_SUCCESS if the key has been -successfully added or a SSH_AGENT_FAILURE if an error occurred. - -2.2.3 Add protocol 2 key - -The OpenSSH agent supports DSA, ECDSA and RSA keys for protocol 2. DSA -keys may be added using the following request - - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ssh-dss" - mpint dsa_p - mpint dsa_q - mpint dsa_g - mpint dsa_public_key - mpint dsa_private_key - string key_comment - constraint[] key_constraints - -DSA certificates may be added with: - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ssh-dss-cert-v00@openssh.com" - string certificate - mpint dsa_private_key - string key_comment - constraint[] key_constraints - -ECDSA keys may be added using the following request - - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ecdsa-sha2-nistp256" | - "ecdsa-sha2-nistp384" | - "ecdsa-sha2-nistp521" - string ecdsa_curve_name - string ecdsa_public_key - mpint ecdsa_private - string key_comment - constraint[] key_constraints - -ECDSA certificates may be added with: - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ecdsa-sha2-nistp256-cert-v01@openssh.com" | - "ecdsa-sha2-nistp384-cert-v01@openssh.com" | - "ecdsa-sha2-nistp521-cert-v01@openssh.com" - string certificate - mpint ecdsa_private_key - string key_comment - constraint[] key_constraints - -ED25519 keys may be added using the following request - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ssh-ed25519" - string ed25519_public_key - string ed25519_private_key || ed25519_public_key - string key_comment - constraint[] key_constraints - -ED25519 certificates may be added with: - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ssh-ed25519-cert-v01@openssh.com" - string certificate - string ed25519_public_key - string ed25519_private_key || ed25519_public_key - string key_comment - constraint[] key_constraints - -For both ssh-ed25519 and ssh-ed25519-cert-v01@openssh.com keys, the private -key has the public key appended (for historical reasons). - -RSA keys may be added with this request: - - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ssh-rsa" - mpint rsa_n - mpint rsa_e - mpint rsa_d - mpint rsa_iqmp - mpint rsa_p - mpint rsa_q - string key_comment - constraint[] key_constraints - -RSA certificates may be added with this request: - - byte SSH2_AGENTC_ADD_IDENTITY or - SSH2_AGENTC_ADD_ID_CONSTRAINED - string "ssh-rsa-cert-v00@openssh.com" - string certificate - mpint rsa_d - mpint rsa_iqmp - mpint rsa_p - mpint rsa_q - string key_comment - constraint[] key_constraints - -Note that the 'rsa_p' and 'rsa_q' parameters are sent in the reverse -order to the protocol 1 add keys message. As with the corresponding -protocol 1 "add key" request, the private key is overspecified to avoid -redundant processing. - -For DSA, ECDSA and RSA key add requests, "key_constraints" may only be -present if the request type is SSH2_AGENTC_ADD_ID_CONSTRAINED. - -The agent will reply with a SSH_AGENT_SUCCESS if the key has been -successfully added or a SSH_AGENT_FAILURE if an error occurred. - -2.2.4 Loading keys from a smartcard - -The OpenSSH agent may have optional smartcard support built in to it. If -so, it supports an operation to load keys from a smartcard. Technically, -only the public components of the keys are loaded into the agent so -this operation really arranges for future private key operations to be -delegated to the smartcard. - - byte SSH_AGENTC_ADD_SMARTCARD_KEY or - SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED - string reader_id - string pin - constraint[] key_constraints - -"reader_id" is an identifier to a smartcard reader and "pin" -is a PIN or passphrase used to unlock the private key(s) on the -device. "key_constraints" may only be present if the request type is -SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED. - -This operation may load all SSH keys that are unlocked using the -"pin" on the specified reader. The type of key loaded (protocol 1 -or protocol 2) will be specified by the smartcard itself, it is not -client-specified. - -The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have -been successfully loaded or a SSH_AGENT_FAILURE if an error occurred. -The agent will also return SSH_AGENT_FAILURE if it does not support -smartcards. - -2.3 Removing multiple keys - -A client may request that an agent delete all protocol 1 keys using the -following request: - - byte SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES - -This message requests the deletion of all protocol 2 keys: - - byte SSH2_AGENTC_REMOVE_ALL_IDENTITIES - -On success, the agent will delete all keys of the requested type and -reply with a SSH_AGENT_SUCCESS message. If an error occurred, the agent -will reply with SSH_AGENT_FAILURE. - -Note that, to delete all keys (both protocol 1 and 2), a client -must send both a SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES and a -SSH2_AGENTC_REMOVE_ALL_IDENTITIES request. - -2.4 Removing specific keys - -2.4.1 Removing a protocol 1 key - -Removal of a protocol 1 key may be requested with the following message: - - byte SSH_AGENTC_REMOVE_RSA_IDENTITY - uint32 key_bits - mpint1 rsa_e - mpint1 rsa_n - -Note that key_bits is strictly redundant, as it may be inferred by the -length of rsa_n. - -The agent will delete any private key matching the specified public key -and return SSH_AGENT_SUCCESS. If no such key was found, the agent will -return SSH_AGENT_FAILURE. - -2.4.2 Removing a protocol 2 key - -Protocol 2 keys may be removed with the following request: - - byte SSH2_AGENTC_REMOVE_IDENTITY - string key_blob - -Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key -Algorithms" for any of the supported protocol 2 key types. - -The agent will delete any private key matching the specified public key -and return SSH_AGENT_SUCCESS. If no such key was found, the agent will -return SSH_AGENT_FAILURE. - -2.4.3 Removing keys loaded from a smartcard - -A client may request that a server remove one or more smartcard-hosted -keys using this message: - - byte SSH_AGENTC_REMOVE_SMARTCARD_KEY - string reader_id - string pin - -"reader_id" the an identifier to a smartcard reader and "pin" is a PIN -or passphrase used to unlock the private key(s) on the device. - -When this message is received, and if the agent supports -smartcard-hosted keys, it will delete all keys that are hosted on the -specified smartcard that may be accessed with the given "pin". - -The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have -been successfully removed or a SSH_AGENT_FAILURE if an error occurred. -The agent will also return SSH_AGENT_FAILURE if it does not support -smartcards. - -2.5 Requesting a list of known keys - -An agent may be requested to list which keys it holds. Different -requests exist for protocol 1 and protocol 2 keys. - -2.5.1 Requesting a list of protocol 1 keys - -To request a list of protocol 1 keys that are held in the agent, a -client may send the following message: - - byte SSH_AGENTC_REQUEST_RSA_IDENTITIES - -The agent will reply with the following message: - - byte SSH_AGENT_RSA_IDENTITIES_ANSWER - uint32 num_keys - -Followed by zero or more consecutive keys, encoded as: - - uint32 bits - mpint1 rsa_e - mpint1 rsa_n - string key_comment - -2.5.2 Requesting a list of protocol 2 keys - -A client may send the following message to request a list of -protocol 2 keys that are stored in the agent: - - byte SSH2_AGENTC_REQUEST_IDENTITIES - -The agent will reply with the following message header: - - byte SSH2_AGENT_IDENTITIES_ANSWER - uint32 num_keys - -Followed by zero or more consecutive keys, encoded as: - - string key_blob - string key_comment - -Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key -Algorithms" for any of the supported protocol 2 key types. - -2.6 Private key operations - -The purpose of the agent is to perform private key operations, such as -signing and encryption without requiring a passphrase to unlock the -key and without allowing the private key itself to be exposed. There -are separate requests for the protocol 1 and protocol 2 private key -operations. - -2.6.1 Protocol 1 private key challenge - -The private key operation used in version 1 of the SSH protocol is -decrypting a challenge that has been encrypted with a public key. -It may be requested using this message: - - byte SSH_AGENTC_RSA_CHALLENGE - uint32 ignored - mpint1 rsa_e - mpint1 rsa_n - mpint1 encrypted_challenge - byte[16] session_id - uint32 response_type /* must be 1 */ - -"rsa_e" and "rsa_n" are used to identify which private key to use. -"encrypted_challenge" is a challenge blob that has (presumably) -been encrypted with the public key and must be in the range -1 <= encrypted_challenge < 2^256. "session_id" is the SSH protocol 1 -session ID (computed from the server host key, the server semi-ephemeral -key and the session cookie). - -"ignored" and "response_type" exist for compatibility with legacy -implementations. "response_type" must be equal to 1; other response -types are not supported. - -On receiving this request, the server decrypts the "encrypted_challenge" -using the private key matching the supplied (rsa_e, rsa_n) values. For -the response derivation, the decrypted challenge is represented as an -unsigned, big-endian integer encoded in a 32 byte buffer (i.e. values -smaller than 2^248 will have leading 0 bytes). - -The response value is then calculated as: - - response = MD5(decrypted_challenge || session_id) - -and returned in the following message - - byte SSH_AGENT_RSA_RESPONSE - byte[16] response - -If the agent cannot find the key specified by the supplied (rsa_e, -rsa_n) then it will return SSH_AGENT_FAILURE. - -2.6.2 Protocol 2 private key signature request - -A client may use the following message to request signing of data using -a protocol 2 key: - - byte SSH2_AGENTC_SIGN_REQUEST - string key_blob - string data - uint32 flags - -Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key -Algorithms" for any of the supported protocol 2 key types. "flags" is -a bit-mask, but at present only one possible value is defined (see below -for its meaning): - - SSH_AGENT_OLD_SIGNATURE 1 - -Upon receiving this request, the agent will look up the private key that -corresponds to the public key contained in key_blob. It will use this -private key to sign the "data" and produce a signature blob using the -key type-specific method described in RFC 4253 section 6.6 "Public Key -Algorithms". - -An exception to this is for "ssh-dss" keys where the "flags" word -contains the value SSH_AGENT_OLD_SIGNATURE. In this case, a legacy -signature encoding is used in lieu of the standard one. In this case, -the DSA signature blob is encoded as: - - byte[40] signature - -The signature will be returned in the response message: - - byte SSH2_AGENT_SIGN_RESPONSE - string signature_blob - -If the agent cannot find the key specified by the supplied key_blob then -it will return SSH_AGENT_FAILURE. - -2.7 Locking or unlocking an agent - -The agent supports temporary locking with a passphrase to suspend -processing of sensitive operations until it has been unlocked with the -same passphrase. To lock an agent, a client send the following request: - - byte SSH_AGENTC_LOCK - string passphrase - -Upon receipt of this message and if the agent is not already locked, -it will suspend processing requests and return a SSH_AGENT_SUCCESS -reply. If the agent is already locked, it will return SSH_AGENT_FAILURE. - -While locked, the agent will refuse all requests except -SSH_AGENTC_UNLOCK, SSH_AGENTC_REQUEST_RSA_IDENTITIES and -SSH2_AGENTC_REQUEST_IDENTITIES. The "request identities" requests are -treated specially by a locked agent: it will always return an empty list -of keys. - -To unlock an agent, a client may request: - - byte SSH_AGENTC_UNLOCK - string passphrase - -If the passphrase matches and the agent is locked, then it will resume -processing all requests and return SSH_AGENT_SUCCESS. If the agent -is not locked or the passphrase does not match then it will return -SSH_AGENT_FAILURE. - -Locking and unlocking affects both protocol 1 and protocol 2 keys. - -3. Protocol message numbers - -3.1 Requests from client to agent for protocol 1 key operations - - SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 - SSH_AGENTC_RSA_CHALLENGE 3 - SSH_AGENTC_ADD_RSA_IDENTITY 7 - SSH_AGENTC_REMOVE_RSA_IDENTITY 8 - SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 - SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24 - -3.2 Requests from client to agent for protocol 2 key operations - - SSH2_AGENTC_REQUEST_IDENTITIES 11 - SSH2_AGENTC_SIGN_REQUEST 13 - SSH2_AGENTC_ADD_IDENTITY 17 - SSH2_AGENTC_REMOVE_IDENTITY 18 - SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 - SSH2_AGENTC_ADD_ID_CONSTRAINED 25 - -3.3 Key-type independent requests from client to agent - - SSH_AGENTC_ADD_SMARTCARD_KEY 20 - SSH_AGENTC_REMOVE_SMARTCARD_KEY 21 - SSH_AGENTC_LOCK 22 - SSH_AGENTC_UNLOCK 23 - SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26 - -3.4 Generic replies from agent to client - - SSH_AGENT_FAILURE 5 - SSH_AGENT_SUCCESS 6 - -3.5 Replies from agent to client for protocol 1 key operations - - SSH_AGENT_RSA_IDENTITIES_ANSWER 2 - SSH_AGENT_RSA_RESPONSE 4 - -3.6 Replies from agent to client for protocol 2 key operations - - SSH2_AGENT_IDENTITIES_ANSWER 12 - SSH2_AGENT_SIGN_RESPONSE 14 - -3.7 Key constraint identifiers - - SSH_AGENT_CONSTRAIN_LIFETIME 1 - SSH_AGENT_CONSTRAIN_CONFIRM 2 - -$OpenBSD: PROTOCOL.agent,v 1.11 2016/05/19 07:45:32 djm Exp $ +https://tools.ietf.org/html/draft-miller-ssh-agent-02 diff --git a/PROTOCOL.certkeys b/PROTOCOL.certkeys index aa6f5ae4c776..42aa8c2a1734 100644 --- a/PROTOCOL.certkeys +++ b/PROTOCOL.certkeys @@ -192,12 +192,13 @@ compatibility. The reserved field is currently unused and is ignored in this version of the protocol. -signature key contains the CA key used to sign the certificate. -The valid key types for CA keys are ssh-rsa, ssh-dss and the ECDSA types -ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521. "Chained" -certificates, where the signature key type is a certificate type itself -are NOT supported. Note that it is possible for a RSA certificate key to -be signed by a DSS or ECDSA CA key and vice-versa. +The signature key field contains the CA key used to sign the +certificate. The valid key types for CA keys are ssh-rsa, +ssh-dss, ssh-ed25519 and the ECDSA types ecdsa-sha2-nistp256, +ecdsa-sha2-nistp384, ecdsa-sha2-nistp521. "Chained" certificates, where +the signature key type is a certificate type itself are NOT supported. +Note that it is possible for a RSA certificate key to be signed by a +Ed25519 or ECDSA CA key and vice-versa. signature is computed over all preceding fields from the initial string up to, and including the signature key. Signatures are computed and @@ -223,6 +224,9 @@ option-specific information (see below). All options are "critical", if an implementation does not recognise a option then the validating party should refuse to accept the certificate. +Custom options should append the originating author or organisation's +domain name to the option name, e.g. "my-option@example.com". + No critical options are defined for host certificates at present. The supported user certificate options and the contents and structure of their data fields are: @@ -254,6 +258,9 @@ as is the requirement that each name appear only once. If an implementation does not recognise an extension, then it should ignore it. +Custom options should append the originating author or organisation's +domain name to the option name, e.g. "my-option@example.com". + No extensions are defined for host certificates at present. The supported user certificate extensions and the contents and structure of their data fields are: @@ -284,4 +291,4 @@ permit-user-rc empty Flag indicating that execution of of this script will not be permitted if this option is not present. -$OpenBSD: PROTOCOL.certkeys,v 1.10 2016/05/03 10:27:59 djm Exp $ +$OpenBSD: PROTOCOL.certkeys,v 1.12 2017/05/31 04:29:44 djm Exp $ diff --git a/README b/README index bda852548a2a..103d43e9b7b7 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -See https://www.openssh.com/releasenotes.html#7.5p1 for the release notes. +See https://www.openssh.com/releasenotes.html#7.6p1 for the release notes. Please read https://www.openssh.com/report.html for bug reporting instructions and note that we do not use Github for bug reporting or @@ -30,7 +30,8 @@ The PAM support is now more functional than the popular packages of commercial ssh-1.2.x. It checks "account" and "session" modules for all logins, not just when using password authentication. -OpenSSH depends on Zlib[3], OpenSSL[4] and optionally PAM[5]. +OpenSSH depends on Zlib[3], OpenSSL[4], and optionally PAM[5] and +libedit[6] There is now several mailing lists for this port of OpenSSH. Please refer to https://www.openssh.com/list.html for details on how to join. @@ -38,7 +39,7 @@ refer to https://www.openssh.com/list.html for details on how to join. Please send bug reports and patches to the mailing list openssh-unix-dev@mindrot.org. The list is open to posting by unsubscribed users. Code contribution are welcomed, but please follow the OpenBSD -style guidelines[6]. +style guidelines[7]. Please refer to the INSTALL document for information on how to install OpenSSH on your system. @@ -61,4 +62,5 @@ References - [5] http://www.openpam.org http://www.kernel.org/pub/linux/libs/pam/ (PAM also is standard on Solaris and HP-UX 11) -[6] http://man.openbsd.org/style.9 +[6] http://thrysoee.dk/editline/ (portable version) +[7] http://man.openbsd.org/style.9 diff --git a/auth-options.c b/auth-options.c index 57b49f7fd751..bed00eef0fe3 100644 --- a/auth-options.c +++ b/auth-options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.c,v 1.72 2016/11/30 02:57:40 djm Exp $ */ +/* $OpenBSD: auth-options.c,v 1.74 2017/09/12 06:32:07 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -61,9 +61,13 @@ char *authorized_principals = NULL; extern ServerOptions options; +/* XXX refactor to be stateless */ + void auth_clear_options(void) { + struct ssh *ssh = active_state; /* XXX */ + no_agent_forwarding_flag = 0; no_port_forwarding_flag = 0; no_pty_flag = 0; @@ -81,7 +85,7 @@ auth_clear_options(void) free(authorized_principals); authorized_principals = NULL; forced_tun_device = -1; - channel_clear_permitted_opens(); + channel_clear_permitted_opens(ssh); } /* @@ -117,9 +121,11 @@ match_flag(const char *opt, int allow_negate, char **optsp, const char *msg) /* * return 1 if access is granted, 0 if not. * side effect: sets key option flags + * XXX remove side effects; fill structure instead. */ int -auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) +auth_parse_options(struct passwd *pw, char *opts, const char *file, + u_long linenum) { struct ssh *ssh = active_state; /* XXX */ const char *cp; @@ -379,7 +385,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) goto bad_option; } if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) - channel_add_permitted_opens(host, port); + channel_add_permitted_opens(ssh, host, port); free(patterns); goto next_option; } diff --git a/auth-options.h b/auth-options.h index 52cbb42aaf87..547f016355a9 100644 --- a/auth-options.h +++ b/auth-options.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.h,v 1.22 2016/11/30 02:57:40 djm Exp $ */ +/* $OpenBSD: auth-options.h,v 1.23 2017/05/31 10:54:00 markus Exp $ */ /* * Author: Tatu Ylonen @@ -33,7 +33,7 @@ extern int forced_tun_device; extern int key_is_cert_authority; extern char *authorized_principals; -int auth_parse_options(struct passwd *, char *, char *, u_long); +int auth_parse_options(struct passwd *, char *, const char *, u_long); void auth_clear_options(void); int auth_cert_options(struct sshkey *, struct passwd *, const char **); diff --git a/auth-pam.c b/auth-pam.c index bc8e5e02d834..de29c04c9c81 100644 --- a/auth-pam.c +++ b/auth-pam.c @@ -106,7 +106,6 @@ extern char *__progname; extern ServerOptions options; extern Buffer loginmsg; -extern int compat20; extern u_int utmp_len; /* so we don't silently change behaviour */ @@ -468,18 +467,16 @@ sshpam_thread(void *ctxtp) if (sshpam_err != PAM_SUCCESS) goto auth_fail; - if (compat20) { - if (!do_pam_account()) { - sshpam_err = PAM_ACCT_EXPIRED; + if (!do_pam_account()) { + sshpam_err = PAM_ACCT_EXPIRED; + goto auth_fail; + } + if (sshpam_authctxt->force_pwchange) { + sshpam_err = pam_chauthtok(sshpam_handle, + PAM_CHANGE_EXPIRED_AUTHTOK); + if (sshpam_err != PAM_SUCCESS) goto auth_fail; - } - if (sshpam_authctxt->force_pwchange) { - sshpam_err = pam_chauthtok(sshpam_handle, - PAM_CHANGE_EXPIRED_AUTHTOK); - if (sshpam_err != PAM_SUCCESS) - goto auth_fail; - sshpam_password_change_required(0); - } + sshpam_password_change_required(0); } buffer_put_cstring(&buffer, "OK"); @@ -929,6 +926,27 @@ finish_pam(void) sshpam_cleanup(); } +static void +expose_authinfo(const char *caller) +{ + char *auth_info; + + /* + * Expose authentication information to PAM. + * The enviornment variable is versioned. Please increment the + * version suffix if the format of session_info changes. + */ + if (sshpam_authctxt->session_info == NULL) + auth_info = xstrdup(""); + else if ((auth_info = sshbuf_dup_string( + sshpam_authctxt->session_info)) == NULL) + fatal("%s: sshbuf_dup_string failed", __func__); + + debug2("%s: auth information in SSH_AUTH_INFO_0", caller); + do_pam_putenv("SSH_AUTH_INFO_0", auth_info); + free(auth_info); +} + u_int do_pam_account(void) { @@ -936,6 +954,8 @@ do_pam_account(void) if (sshpam_account_status != -1) return (sshpam_account_status); + expose_authinfo(__func__); + sshpam_err = pam_acct_mgmt(sshpam_handle, 0); debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err, pam_strerror(sshpam_handle, sshpam_err)); @@ -1060,6 +1080,9 @@ void do_pam_session(void) { debug3("PAM: opening session"); + + expose_authinfo(__func__); + sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, (const void *)&store_conv); if (sshpam_err != PAM_SUCCESS) diff --git a/auth.c b/auth.c index 6ee6116dfb2f..a449061741af 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.119 2016/12/15 21:29:05 dtucker Exp $ */ +/* $OpenBSD: auth.c,v 1.124 2017/09/12 06:32:07 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -43,9 +43,6 @@ #ifdef USE_SHADOW #include #endif -#ifdef HAVE_LIBGEN_H -#include -#endif #include #include #include @@ -267,21 +264,41 @@ allowed_user(struct passwd * pw) return 1; } -void -auth_info(Authctxt *authctxt, const char *fmt, ...) +/* + * Formats any key left in authctxt->auth_method_key for inclusion in + * auth_log()'s message. Also includes authxtct->auth_method_info if present. + */ +static char * +format_method_key(Authctxt *authctxt) { - va_list ap; - int i; + const struct sshkey *key = authctxt->auth_method_key; + const char *methinfo = authctxt->auth_method_info; + char *fp, *ret = NULL; - free(authctxt->info); - authctxt->info = NULL; + if (key == NULL) + return NULL; - va_start(ap, fmt); - i = vasprintf(&authctxt->info, fmt, ap); - va_end(ap); - - if (i < 0 || authctxt->info == NULL) - fatal("vasprintf failed"); + if (key_is_cert(key)) { + fp = sshkey_fingerprint(key->cert->signature_key, + options.fingerprint_hash, SSH_FP_DEFAULT); + xasprintf(&ret, "%s ID %s (serial %llu) CA %s %s%s%s", + sshkey_type(key), key->cert->key_id, + (unsigned long long)key->cert->serial, + sshkey_type(key->cert->signature_key), + fp == NULL ? "(null)" : fp, + methinfo == NULL ? "" : ", ", + methinfo == NULL ? "" : methinfo); + free(fp); + } else { + fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT); + xasprintf(&ret, "%s %s%s%s", sshkey_type(key), + fp == NULL ? "(null)" : fp, + methinfo == NULL ? "" : ", ", + methinfo == NULL ? "" : methinfo); + free(fp); + } + return ret; } void @@ -290,7 +307,8 @@ auth_log(Authctxt *authctxt, int authenticated, int partial, { struct ssh *ssh = active_state; /* XXX */ void (*authlog) (const char *fmt,...) = verbose; - char *authmsg; + const char *authmsg; + char *extra = NULL; if (use_privsep && !mm_is_monitor() && !authctxt->postponed) return; @@ -309,6 +327,11 @@ auth_log(Authctxt *authctxt, int authenticated, int partial, else authmsg = authenticated ? "Accepted" : "Failed"; + if ((extra = format_method_key(authctxt)) == NULL) { + if (authctxt->auth_method_info != NULL) + extra = xstrdup(authctxt->auth_method_info); + } + authlog("%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s", authmsg, method, @@ -317,10 +340,10 @@ auth_log(Authctxt *authctxt, int authenticated, int partial, authctxt->user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), - authctxt->info != NULL ? ": " : "", - authctxt->info != NULL ? authctxt->info : ""); - free(authctxt->info); - authctxt->info = NULL; + extra != NULL ? ": " : "", + extra != NULL ? extra : ""); + + free(extra); #ifdef CUSTOM_FAILED_LOGIN if (authenticated == 0 && !authctxt->postponed && @@ -428,7 +451,7 @@ authorized_principals_file(struct passwd *pw) /* return ok if key exists in sysfile or userfile */ HostStatus -check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, +check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host, const char *sysfile, const char *userfile) { char *user_hostfile; @@ -472,98 +495,6 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, return host_status; } -/* - * Check a given path for security. This is defined as all components - * of the path to the file must be owned by either the owner of - * of the file or root and no directories must be group or world writable. - * - * XXX Should any specific check be done for sym links ? - * - * Takes a file name, its stat information (preferably from fstat() to - * avoid races), the uid of the expected owner, their home directory and an - * error buffer plus max size as arguments. - * - * Returns 0 on success and -1 on failure - */ -int -auth_secure_path(const char *name, struct stat *stp, const char *pw_dir, - uid_t uid, char *err, size_t errlen) -{ - char buf[PATH_MAX], homedir[PATH_MAX]; - char *cp; - int comparehome = 0; - struct stat st; - - if (realpath(name, buf) == NULL) { - snprintf(err, errlen, "realpath %s failed: %s", name, - strerror(errno)); - return -1; - } - if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL) - comparehome = 1; - - if (!S_ISREG(stp->st_mode)) { - snprintf(err, errlen, "%s is not a regular file", buf); - return -1; - } - if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || - (stp->st_mode & 022) != 0) { - snprintf(err, errlen, "bad ownership or modes for file %s", - buf); - return -1; - } - - /* for each component of the canonical path, walking upwards */ - for (;;) { - if ((cp = dirname(buf)) == NULL) { - snprintf(err, errlen, "dirname() failed"); - return -1; - } - strlcpy(buf, cp, sizeof(buf)); - - if (stat(buf, &st) < 0 || - (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || - (st.st_mode & 022) != 0) { - snprintf(err, errlen, - "bad ownership or modes for directory %s", buf); - return -1; - } - - /* If are past the homedir then we can stop */ - if (comparehome && strcmp(homedir, buf) == 0) - break; - - /* - * dirname should always complete with a "/" path, - * but we can be paranoid and check for "." too - */ - if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) - break; - } - return 0; -} - -/* - * Version of secure_path() that accepts an open file descriptor to - * avoid races. - * - * Returns 0 on success and -1 on failure - */ -static int -secure_filename(FILE *f, const char *file, struct passwd *pw, - char *err, size_t errlen) -{ - struct stat st; - - /* check the open file to avoid races */ - if (fstat(fileno(f), &st) < 0) { - snprintf(err, errlen, "cannot stat file %s: %s", - file, strerror(errno)); - return -1; - } - return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); -} - static FILE * auth_openfile(const char *file, struct passwd *pw, int strict_modes, int log_missing, char *file_type) @@ -596,7 +527,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes, return NULL; } if (strict_modes && - secure_filename(f, file, pw, line, sizeof(line)) != 0) { + safe_path_fd(fileno(f), file, pw, line, sizeof(line)) != 0) { fclose(f); logit("Authentication refused: %s", line); auth_debug_add("Ignored %s: %s", file_type, line); @@ -635,6 +566,8 @@ getpwnamallow(const char *user) ci->user = user; parse_server_match_config(&options, ci); + log_change_level(options.log_level); + process_permitopen(ssh, &options); #if defined(_AIX) && defined(HAVE_SETAUTHDB) aix_setauthdb(user); @@ -694,7 +627,7 @@ getpwnamallow(const char *user) /* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */ int -auth_key_is_revoked(Key *key) +auth_key_is_revoked(struct sshkey *key) { char *fp = NULL; int r; diff --git a/auth.h b/auth.h index 338a62da72a4..29835ae92750 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.89 2016/08/13 17:47:41 markus Exp $ */ +/* $OpenBSD: auth.h,v 1.93 2017/08/18 05:36:45 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -44,6 +44,7 @@ struct ssh; struct sshkey; +struct sshbuf; typedef struct Authctxt Authctxt; typedef struct Authmethod Authmethod; @@ -62,13 +63,17 @@ struct Authctxt { char *service; struct passwd *pw; /* set if 'valid' */ char *style; + + /* Method lists for multiple authentication */ + char **auth_methods; /* modified from server config */ + u_int num_auth_methods; + + /* Authentication method-specific data */ + void *methoddata; void *kbdintctxt; - char *info; /* Extra info for next auth_log */ #ifdef BSD_AUTH auth_session_t *as; #endif - char **auth_methods; /* modified from server config */ - u_int num_auth_methods; #ifdef KRB5 krb5_context krb5_ctx; krb5_ccache krb5_fwd_ccache; @@ -76,12 +81,20 @@ struct Authctxt { char *krb5_ticket_file; char *krb5_ccname; #endif - Buffer *loginmsg; - void *methoddata; + struct sshbuf *loginmsg; - struct sshkey **prev_userkeys; - u_int nprev_userkeys; + /* Authentication keys already used; these will be refused henceforth */ + struct sshkey **prev_keys; + u_int nprev_keys; + + /* Last used key and ancilliary information from active auth method */ + struct sshkey *auth_method_key; + char *auth_method_info; + + /* Information exposed to session */ + struct sshbuf *session_info; /* Auth info for environment */ }; + /* * Every authentication method has to handle authentication requests for * non-existing users, or for users that are not allowed to login. In this @@ -91,7 +104,7 @@ struct Authctxt { struct Authmethod { char *name; - int (*userauth)(Authctxt *authctxt); + int (*userauth)(struct ssh *); int *enabled; }; @@ -117,16 +130,21 @@ auth_rhosts2(struct passwd *, const char *, const char *, const char *); int auth_password(Authctxt *, const char *); -int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); -int user_key_allowed(struct passwd *, Key *, int); -void pubkey_auth_info(Authctxt *, const Key *, const char *, ...) - __attribute__((__format__ (printf, 3, 4))); -void auth2_record_userkey(Authctxt *, struct sshkey *); -int auth2_userkey_already_used(Authctxt *, struct sshkey *); +int hostbased_key_allowed(struct passwd *, const char *, char *, + struct sshkey *); +int user_key_allowed(struct passwd *, struct sshkey *, int); +int auth2_key_already_used(Authctxt *, const struct sshkey *); -struct stat; -int auth_secure_path(const char *, struct stat *, const char *, uid_t, - char *, size_t); +/* + * Handling auth method-specific information for logging and prevention + * of key reuse during multiple authentication. + */ +void auth2_authctxt_reset_info(Authctxt *); +void auth2_record_key(Authctxt *, int, const struct sshkey *); +void auth2_record_info(Authctxt *authctxt, const char *, ...) + __attribute__((__format__ (printf, 2, 3))) + __attribute__((__nonnull__ (2))); +void auth2_update_session_info(Authctxt *, const char *, const char *); #ifdef KRB5 int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *); @@ -149,12 +167,9 @@ void disable_forwarding(void); void do_authentication2(Authctxt *); -void auth_info(Authctxt *authctxt, const char *, ...) - __attribute__((__format__ (printf, 2, 3))) - __attribute__((__nonnull__ (2))); void auth_log(Authctxt *, int, int, const char *, const char *); void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn)); -void userauth_finish(Authctxt *, int, const char *, const char *); +void userauth_finish(struct ssh *, int, const char *, const char *); int auth_root_allowed(const char *); void userauth_send_banner(const char *); @@ -167,8 +182,8 @@ int auth2_method_allowed(Authctxt *, const char *, const char *); void privsep_challenge_enable(void); -int auth2_challenge(Authctxt *, char *); -void auth2_challenge_stop(Authctxt *); +int auth2_challenge(struct ssh *, char *); +void auth2_challenge_stop(struct ssh *); int bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **); int bsdauth_respond(void *, u_int, char **); int skey_query(void *, char **, char **, u_int *, char ***, u_int **); @@ -182,22 +197,22 @@ char *authorized_principals_file(struct passwd *); FILE *auth_openkeyfile(const char *, struct passwd *, int); FILE *auth_openprincipals(const char *, struct passwd *, int); -int auth_key_is_revoked(Key *); +int auth_key_is_revoked(struct sshkey *); const char *auth_get_canonical_hostname(struct ssh *, int); HostStatus -check_key_in_hostfiles(struct passwd *, Key *, const char *, +check_key_in_hostfiles(struct passwd *, struct sshkey *, const char *, const char *, const char *); /* hostkey handling */ -Key *get_hostkey_by_index(int); -Key *get_hostkey_public_by_index(int, struct ssh *); -Key *get_hostkey_public_by_type(int, int, struct ssh *); -Key *get_hostkey_private_by_type(int, int, struct ssh *); -int get_hostkey_index(Key *, int, struct ssh *); -int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *, - const u_char *, size_t, const char *, u_int); +struct sshkey *get_hostkey_by_index(int); +struct sshkey *get_hostkey_public_by_index(int, struct ssh *); +struct sshkey *get_hostkey_public_by_type(int, int, struct ssh *); +struct sshkey *get_hostkey_private_by_type(int, int, struct ssh *); +int get_hostkey_index(struct sshkey *, int, struct ssh *); +int sshd_hostkey_sign(struct sshkey *, struct sshkey *, u_char **, + size_t *, const u_char *, size_t, const char *, u_int); /* debug messages during authentication */ void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); diff --git a/auth2-chall.c b/auth2-chall.c index ead48031808d..11c8d31b3566 100644 --- a/auth2-chall.c +++ b/auth2-chall.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-chall.c,v 1.44 2016/05/02 08:49:03 djm Exp $ */ +/* $OpenBSD: auth2-chall.c,v 1.48 2017/05/30 14:29:59 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Per Allansson. All rights reserved. @@ -47,9 +47,9 @@ /* import */ extern ServerOptions options; -static int auth2_challenge_start(Authctxt *); +static int auth2_challenge_start(struct ssh *); static int send_userauth_info_request(Authctxt *); -static int input_userauth_info_response(int, u_int32_t, void *); +static int input_userauth_info_response(int, u_int32_t, struct ssh *); #ifdef BSD_AUTH extern KbdintDevice bsdauth_device; @@ -195,8 +195,9 @@ kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt) * wait for the response. */ int -auth2_challenge(Authctxt *authctxt, char *devs) +auth2_challenge(struct ssh *ssh, char *devs) { + Authctxt *authctxt = ssh->authctxt; debug("auth2_challenge: user=%s devs=%s", authctxt->user ? authctxt->user : "", devs ? devs : ""); @@ -205,15 +206,16 @@ auth2_challenge(Authctxt *authctxt, char *devs) return 0; if (authctxt->kbdintctxt == NULL) authctxt->kbdintctxt = kbdint_alloc(devs); - return auth2_challenge_start(authctxt); + return auth2_challenge_start(ssh); } /* unregister kbd-int callbacks and context */ void -auth2_challenge_stop(Authctxt *authctxt) +auth2_challenge_stop(struct ssh *ssh) { + Authctxt *authctxt = ssh->authctxt; /* unregister callback */ - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); if (authctxt->kbdintctxt != NULL) { kbdint_free(authctxt->kbdintctxt); authctxt->kbdintctxt = NULL; @@ -222,29 +224,30 @@ auth2_challenge_stop(Authctxt *authctxt) /* side effect: sets authctxt->postponed if a reply was sent*/ static int -auth2_challenge_start(Authctxt *authctxt) +auth2_challenge_start(struct ssh *ssh) { + Authctxt *authctxt = ssh->authctxt; KbdintAuthctxt *kbdintctxt = authctxt->kbdintctxt; debug2("auth2_challenge_start: devices %s", kbdintctxt->devices ? kbdintctxt->devices : ""); if (kbdint_next_device(authctxt, kbdintctxt) == 0) { - auth2_challenge_stop(authctxt); + auth2_challenge_stop(ssh); return 0; } debug("auth2_challenge_start: trying authentication method '%s'", kbdintctxt->device->name); if ((kbdintctxt->ctxt = kbdintctxt->device->init_ctx(authctxt)) == NULL) { - auth2_challenge_stop(authctxt); + auth2_challenge_stop(ssh); return 0; } if (send_userauth_info_request(authctxt) == 0) { - auth2_challenge_stop(authctxt); + auth2_challenge_stop(ssh); return 0; } - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE, &input_userauth_info_response); authctxt->postponed = 1; @@ -285,9 +288,9 @@ send_userauth_info_request(Authctxt *authctxt) } static int -input_userauth_info_response(int type, u_int32_t seq, void *ctxt) +input_userauth_info_response(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; KbdintAuthctxt *kbdintctxt; int authenticated = 0, res; u_int i, nresp; @@ -340,14 +343,14 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt) devicename = kbdintctxt->device->name; if (!authctxt->postponed) { if (authenticated) { - auth2_challenge_stop(authctxt); + auth2_challenge_stop(ssh); } else { /* start next device */ /* may set authctxt->postponed */ - auth2_challenge_start(authctxt); + auth2_challenge_start(ssh); } } - userauth_finish(authctxt, authenticated, "keyboard-interactive", + userauth_finish(ssh, authenticated, "keyboard-interactive", devicename); return 0; } diff --git a/auth2-gss.c b/auth2-gss.c index 1ca8357731ca..589283b72041 100644 --- a/auth2-gss.c +++ b/auth2-gss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-gss.c,v 1.22 2015/01/19 20:07:45 markus Exp $ */ +/* $OpenBSD: auth2-gss.c,v 1.26 2017/06/24 06:34:38 djm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -48,18 +48,19 @@ extern ServerOptions options; -static int input_gssapi_token(int type, u_int32_t plen, void *ctxt); -static int input_gssapi_mic(int type, u_int32_t plen, void *ctxt); -static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); -static int input_gssapi_errtok(int, u_int32_t, void *); +static int input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh); +static int input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh); +static int input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh); +static int input_gssapi_errtok(int, u_int32_t, struct ssh *); /* * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like) */ static int -userauth_gssapi(Authctxt *authctxt) +userauth_gssapi(struct ssh *ssh) { + Authctxt *authctxt = ssh->authctxt; gss_OID_desc goid = {0, NULL}; Gssctxt *ctxt = NULL; int mechs; @@ -119,17 +120,17 @@ userauth_gssapi(Authctxt *authctxt) packet_send(); free(doid); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); authctxt->postponed = 1; return (0); } static int -input_gssapi_token(int type, u_int32_t plen, void *ctxt) +input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; @@ -157,8 +158,8 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) packet_send(); } authctxt->postponed = 0; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - userauth_finish(authctxt, 0, "gssapi-with-mic", NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + userauth_finish(ssh, 0, "gssapi-with-mic", NULL); } else { if (send_tok.length != 0) { packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); @@ -166,12 +167,12 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) packet_send(); } if (maj_status == GSS_S_COMPLETE) { - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); if (flags & GSS_C_INTEG_FLAG) - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC, &input_gssapi_mic); else - dispatch_set( + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, &input_gssapi_exchange_complete); } @@ -182,9 +183,9 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) } static int -input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) +input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; @@ -207,8 +208,8 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) free(recv_tok.value); /* We can't return anything to the client, even if we wanted to */ - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); /* The client will have already moved on to the next auth */ @@ -223,10 +224,11 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) */ static int -input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) +input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; int authenticated; + const char *displayname; if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) fatal("No authentication or GSSAPI context"); @@ -240,24 +242,29 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); + if ((!use_privsep || mm_is_monitor()) && + (displayname = ssh_gssapi_displayname()) != NULL) + auth2_record_info(authctxt, "%s", displayname); + authctxt->postponed = 0; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); - userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); + userauth_finish(ssh, authenticated, "gssapi-with-mic", NULL); return 0; } static int -input_gssapi_mic(int type, u_int32_t plen, void *ctxt) +input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; int authenticated = 0; Buffer b; gss_buffer_desc mic, gssbuf; u_int len; + const char *displayname; if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) fatal("No authentication or GSSAPI context"); @@ -281,12 +288,16 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt) buffer_free(&b); free(mic.value); + if ((!use_privsep || mm_is_monitor()) && + (displayname = ssh_gssapi_displayname()) != NULL) + auth2_record_info(authctxt, "%s", displayname); + authctxt->postponed = 0; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); - userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); + userauth_finish(ssh, authenticated, "gssapi-with-mic", NULL); return 0; } diff --git a/auth2-hostbased.c b/auth2-hostbased.c index 1b3c3b20297f..92758b38c19d 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.26 2016/03/07 19:02:43 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.31 2017/06/24 06:34:38 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -39,7 +39,7 @@ #include "misc.h" #include "servconf.h" #include "compat.h" -#include "key.h" +#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "canohost.h" @@ -48,6 +48,7 @@ #endif #include "monitor_wrap.h" #include "pathnames.h" +#include "ssherr.h" #include "match.h" /* import */ @@ -56,54 +57,56 @@ extern u_char *session_id2; extern u_int session_id2_len; static int -userauth_hostbased(Authctxt *authctxt) +userauth_hostbased(struct ssh *ssh) { - Buffer b; - Key *key = NULL; + Authctxt *authctxt = ssh->authctxt; + struct sshbuf *b; + struct sshkey *key = NULL; char *pkalg, *cuser, *chost, *service; u_char *pkblob, *sig; - u_int alen, blen, slen; - int pktype; - int authenticated = 0; + size_t alen, blen, slen; + int r, pktype, authenticated = 0; if (!authctxt->valid) { - debug2("userauth_hostbased: disabled because of invalid user"); + debug2("%s: disabled because of invalid user", __func__); return 0; } - pkalg = packet_get_string(&alen); - pkblob = packet_get_string(&blen); - chost = packet_get_string(NULL); - cuser = packet_get_string(NULL); - sig = packet_get_string(&slen); + /* XXX use sshkey_froms() */ + if ((r = sshpkt_get_cstring(ssh, &pkalg, &alen)) != 0 || + (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 || + (r = sshpkt_get_cstring(ssh, &chost, NULL)) != 0 || + (r = sshpkt_get_cstring(ssh, &cuser, NULL)) != 0 || + (r = sshpkt_get_string(ssh, &sig, &slen)) != 0) + fatal("%s: packet parsing: %s", __func__, ssh_err(r)); - debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d", + debug("%s: cuser %s chost %s pkalg %s slen %zu", __func__, cuser, chost, pkalg, slen); #ifdef DEBUG_PK debug("signature:"); - buffer_init(&b); - buffer_append(&b, sig, slen); - buffer_dump(&b); - buffer_free(&b); + sshbuf_dump_data(sig, siglen, stderr); #endif - pktype = key_type_from_name(pkalg); + pktype = sshkey_type_from_name(pkalg); if (pktype == KEY_UNSPEC) { /* this is perfectly legal */ - logit("userauth_hostbased: unsupported " - "public key algorithm: %s", pkalg); + logit("%s: unsupported public key algorithm: %s", + __func__, pkalg); + goto done; + } + if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { + error("%s: key_from_blob: %s", __func__, ssh_err(r)); goto done; } - key = key_from_blob(pkblob, blen); if (key == NULL) { - error("userauth_hostbased: cannot decode key: %s", pkalg); + error("%s: cannot decode key: %s", __func__, pkalg); goto done; } if (key->type != pktype) { - error("userauth_hostbased: type mismatch for decoded key " - "(received %d, expected %d)", key->type, pktype); + error("%s: type mismatch for decoded key " + "(received %d, expected %d)", __func__, key->type, pktype); goto done; } - if (key_type_plain(key->type) == KEY_RSA && - (datafellows & SSH_BUG_RSASIGMD5) != 0) { + if (sshkey_type_plain(key->type) == KEY_RSA && + (ssh->compat & SSH_BUG_RSASIGMD5) != 0) { error("Refusing RSA key because peer uses unsafe " "signature format"); goto done; @@ -115,38 +118,40 @@ userauth_hostbased(Authctxt *authctxt) goto done; } - service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : + service = ssh->compat & SSH_BUG_HBSERVICE ? "ssh-userauth" : authctxt->service; - buffer_init(&b); - buffer_put_string(&b, session_id2, session_id2_len); + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, authctxt->user); - buffer_put_cstring(&b, service); - buffer_put_cstring(&b, "hostbased"); - buffer_put_string(&b, pkalg, alen); - buffer_put_string(&b, pkblob, blen); - buffer_put_cstring(&b, chost); - buffer_put_cstring(&b, cuser); + if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || + (r = sshbuf_put_cstring(b, authctxt->user)) != 0 || + (r = sshbuf_put_cstring(b, service)) != 0 || + (r = sshbuf_put_cstring(b, "hostbased")) != 0 || + (r = sshbuf_put_string(b, pkalg, alen)) != 0 || + (r = sshbuf_put_string(b, pkblob, blen)) != 0 || + (r = sshbuf_put_cstring(b, chost)) != 0 || + (r = sshbuf_put_cstring(b, cuser)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); #ifdef DEBUG_PK - buffer_dump(&b); + sshbuf_dump(b, stderr); #endif - pubkey_auth_info(authctxt, key, + auth2_record_info(authctxt, "client user \"%.100s\", client host \"%.100s\"", cuser, chost); /* test for allowed key and correct signature */ authenticated = 0; if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && - PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b))) == 1) + PRIVSEP(sshkey_verify(key, sig, slen, + sshbuf_ptr(b), sshbuf_len(b), ssh->compat)) == 0) authenticated = 1; - buffer_free(&b); + auth2_record_key(authctxt, authenticated, key); + sshbuf_free(b); done: - debug2("userauth_hostbased: authenticated %d", authenticated); - if (key != NULL) - key_free(key); + debug2("%s: authenticated %d", __func__, authenticated); + sshkey_free(key); free(pkalg); free(pkblob); free(cuser); @@ -158,7 +163,7 @@ userauth_hostbased(Authctxt *authctxt) /* return 1 if given hostkey is allowed */ int hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, - Key *key) + struct sshkey *key) { struct ssh *ssh = active_state; /* XXX */ const char *resolvedname, *ipaddr, *lookup, *reason; @@ -203,8 +208,8 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, } debug2("%s: access allowed by auth_rhosts2", __func__); - if (key_is_cert(key) && - key_cert_check_authority(key, 1, 0, lookup, &reason)) { + if (sshkey_is_cert(key) && + sshkey_cert_check_authority(key, 1, 0, lookup, &reason)) { error("%s", reason); auth_debug_add("%s", reason); return 0; @@ -223,20 +228,20 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, } if (host_status == HOST_OK) { - if (key_is_cert(key)) { + if (sshkey_is_cert(key)) { if ((fp = sshkey_fingerprint(key->cert->signature_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal("%s: sshkey_fingerprint fail", __func__); verbose("Accepted certificate ID \"%s\" signed by " "%s CA %s from %s@%s", key->cert->key_id, - key_type(key->cert->signature_key), fp, + sshkey_type(key->cert->signature_key), fp, cuser, lookup); } else { if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal("%s: sshkey_fingerprint fail", __func__); verbose("Accepted %s public key %s from %s@%s", - key_type(key), fp, cuser, lookup); + sshkey_type(key), fp, cuser, lookup); } free(fp); } diff --git a/auth2-kbdint.c b/auth2-kbdint.c index bf75c6059f1e..86aad8ddce8b 100644 --- a/auth2-kbdint.c +++ b/auth2-kbdint.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-kbdint.c,v 1.7 2014/07/15 15:54:14 millert Exp $ */ +/* $OpenBSD: auth2-kbdint.c,v 1.8 2017/05/30 14:29:59 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -43,7 +43,7 @@ extern ServerOptions options; static int -userauth_kbdint(Authctxt *authctxt) +userauth_kbdint(struct ssh *ssh) { int authenticated = 0; char *lang, *devs; @@ -55,7 +55,7 @@ userauth_kbdint(Authctxt *authctxt) debug("keyboard-interactive devs %s", devs); if (options.challenge_response_authentication) - authenticated = auth2_challenge(authctxt, devs); + authenticated = auth2_challenge(ssh, devs); free(devs); free(lang); diff --git a/auth2-none.c b/auth2-none.c index e71e2219cff1..35d25fa6349f 100644 --- a/auth2-none.c +++ b/auth2-none.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-none.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */ +/* $OpenBSD: auth2-none.c,v 1.20 2017/05/30 14:29:59 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -37,7 +37,7 @@ #include "atomicio.h" #include "xmalloc.h" -#include "key.h" +#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "packet.h" @@ -47,6 +47,7 @@ #include "servconf.h" #include "compat.h" #include "ssh2.h" +#include "ssherr.h" #ifdef GSSAPI #include "ssh-gss.h" #endif @@ -59,12 +60,15 @@ extern ServerOptions options; static int none_enabled = 1; static int -userauth_none(Authctxt *authctxt) +userauth_none(struct ssh *ssh) { + int r; + none_enabled = 0; - packet_check_eom(); + if ((r = sshpkt_get_end(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); if (options.permit_empty_passwd && options.password_authentication) - return (PRIVSEP(auth_password(authctxt, ""))); + return (PRIVSEP(auth_password(ssh->authctxt, ""))); return (0); } diff --git a/auth2-passwd.c b/auth2-passwd.c index b638e8715bb2..5f7ba32440b0 100644 --- a/auth2-passwd.c +++ b/auth2-passwd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-passwd.c,v 1.12 2014/07/15 15:54:14 millert Exp $ */ +/* $OpenBSD: auth2-passwd.c,v 1.14 2017/05/30 14:29:59 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -30,10 +30,10 @@ #include #include -#include "xmalloc.h" #include "packet.h" +#include "ssherr.h" #include "log.h" -#include "key.h" +#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "buffer.h" @@ -48,26 +48,22 @@ extern ServerOptions options; static int -userauth_passwd(Authctxt *authctxt) +userauth_passwd(struct ssh *ssh) { - char *password, *newpass; - int authenticated = 0; - int change; - u_int len, newlen; + char *password; + int authenticated = 0, r; + u_char change; + size_t len; - change = packet_get_char(); - password = packet_get_string(&len); - if (change) { - /* discard new password from packet */ - newpass = packet_get_string(&newlen); - explicit_bzero(newpass, newlen); - free(newpass); - } - packet_check_eom(); + if ((r = sshpkt_get_u8(ssh, &change)) != 0 || + (r = sshpkt_get_cstring(ssh, &password, &len)) != 0 || + (change && (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) || + (r = sshpkt_get_end(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); if (change) logit("password change not supported"); - else if (PRIVSEP(auth_password(authctxt, password)) == 1) + else if (PRIVSEP(auth_password(ssh->authctxt, password)) == 1) authenticated = 1; explicit_bzero(password, len); free(password); diff --git a/auth2-pubkey.c b/auth2-pubkey.c index 3e5706f4dbef..169839b01ed7 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.62 2017/01/30 01:03:00 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.71 2017/09/07 23:48:09 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -27,7 +27,6 @@ #include #include -#include #include #include @@ -52,7 +51,7 @@ #include "misc.h" #include "servconf.h" #include "compat.h" -#include "key.h" +#include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "pathnames.h" @@ -75,42 +74,52 @@ extern u_char *session_id2; extern u_int session_id2_len; static int -userauth_pubkey(Authctxt *authctxt) +userauth_pubkey(struct ssh *ssh) { - Buffer b; - Key *key = NULL; - char *pkalg, *userstyle, *fp = NULL; - u_char *pkblob, *sig; - u_int alen, blen, slen; - int have_sig, pktype; + Authctxt *authctxt = ssh->authctxt; + struct sshbuf *b; + struct sshkey *key = NULL; + char *pkalg, *userstyle = NULL, *fp = NULL; + u_char *pkblob, *sig, have_sig; + size_t blen, slen; + int r, pktype; int authenticated = 0; if (!authctxt->valid) { debug2("%s: disabled because of invalid user", __func__); return 0; } - have_sig = packet_get_char(); - if (datafellows & SSH_BUG_PKAUTH) { + if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0) + fatal("%s: sshpkt_get_u8 failed: %s", __func__, ssh_err(r)); + if (ssh->compat & SSH_BUG_PKAUTH) { debug2("%s: SSH_BUG_PKAUTH", __func__); + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); /* no explicit pkalg given */ - pkblob = packet_get_string(&blen); - buffer_init(&b); - buffer_append(&b, pkblob, blen); /* so we have to extract the pkalg from the pkblob */ - pkalg = buffer_get_string(&b, &alen); - buffer_free(&b); + /* XXX use sshbuf_from() */ + if ((r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 || + (r = sshbuf_put(b, pkblob, blen)) != 0 || + (r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0) + fatal("%s: failed: %s", __func__, ssh_err(r)); + sshbuf_free(b); } else { - pkalg = packet_get_string(&alen); - pkblob = packet_get_string(&blen); + if ((r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 || + (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0) + fatal("%s: sshpkt_get_cstring failed: %s", + __func__, ssh_err(r)); } - pktype = key_type_from_name(pkalg); + pktype = sshkey_type_from_name(pkalg); if (pktype == KEY_UNSPEC) { /* this is perfectly legal */ logit("%s: unsupported public key algorithm: %s", __func__, pkalg); goto done; } - key = key_from_blob(pkblob, blen); + if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { + error("%s: could not parse key: %s", __func__, ssh_err(r)); + goto done; + } if (key == NULL) { error("%s: cannot decode key: %s", __func__, pkalg); goto done; @@ -120,15 +129,15 @@ userauth_pubkey(Authctxt *authctxt) "(received %d, expected %d)", __func__, key->type, pktype); goto done; } - if (key_type_plain(key->type) == KEY_RSA && - (datafellows & SSH_BUG_RSASIGMD5) != 0) { + if (sshkey_type_plain(key->type) == KEY_RSA && + (ssh->compat & SSH_BUG_RSASIGMD5) != 0) { logit("Refusing RSA key because client uses unsafe " "signature scheme"); goto done; } fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); - if (auth2_userkey_already_used(authctxt, key)) { - logit("refusing previously-used %s key", key_type(key)); + if (auth2_key_already_used(authctxt, key)) { + logit("refusing previously-used %s key", sshkey_type(key)); goto done; } if (match_pattern_list(sshkey_ssh_name(key), @@ -141,54 +150,65 @@ userauth_pubkey(Authctxt *authctxt) if (have_sig) { debug3("%s: have signature for %s %s", __func__, sshkey_type(key), fp); - sig = packet_get_string(&slen); - packet_check_eom(); - buffer_init(&b); - if (datafellows & SSH_OLD_SESSIONID) { - buffer_append(&b, session_id2, session_id2_len); + if ((r = sshpkt_get_string(ssh, &sig, &slen)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if (ssh->compat & SSH_OLD_SESSIONID) { + if ((r = sshbuf_put(b, session_id2, + session_id2_len)) != 0) + fatal("%s: sshbuf_put session id: %s", + __func__, ssh_err(r)); } else { - buffer_put_string(&b, session_id2, session_id2_len); + if ((r = sshbuf_put_string(b, session_id2, + session_id2_len)) != 0) + fatal("%s: sshbuf_put_string session id: %s", + __func__, ssh_err(r)); } /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); - buffer_put_cstring(&b, userstyle); - free(userstyle); - buffer_put_cstring(&b, - datafellows & SSH_BUG_PKSERVICE ? - "ssh-userauth" : - authctxt->service); - if (datafellows & SSH_BUG_PKAUTH) { - buffer_put_char(&b, have_sig); + if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || + (r = sshbuf_put_cstring(b, userstyle)) != 0 || + (r = sshbuf_put_cstring(b, ssh->compat & SSH_BUG_PKSERVICE ? + "ssh-userauth" : authctxt->service)) != 0) + fatal("%s: build packet failed: %s", + __func__, ssh_err(r)); + if (ssh->compat & SSH_BUG_PKAUTH) { + if ((r = sshbuf_put_u8(b, have_sig)) != 0) + fatal("%s: build packet failed: %s", + __func__, ssh_err(r)); } else { - buffer_put_cstring(&b, "publickey"); - buffer_put_char(&b, have_sig); - buffer_put_cstring(&b, pkalg); + if ((r = sshbuf_put_cstring(b, "publickey")) != 0 || + (r = sshbuf_put_u8(b, have_sig)) != 0 || + (r = sshbuf_put_cstring(b, pkalg) != 0)) + fatal("%s: build packet failed: %s", + __func__, ssh_err(r)); } - buffer_put_string(&b, pkblob, blen); + if ((r = sshbuf_put_string(b, pkblob, blen)) != 0) + fatal("%s: build packet failed: %s", + __func__, ssh_err(r)); #ifdef DEBUG_PK - buffer_dump(&b); + sshbuf_dump(b, stderr); #endif - pubkey_auth_info(authctxt, key, NULL); /* test for correct signature */ authenticated = 0; if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) && - PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b))) == 1) { + PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b), + sshbuf_len(b), ssh->compat)) == 0) { authenticated = 1; - /* Record the successful key to prevent reuse */ - auth2_record_userkey(authctxt, key); - key = NULL; /* Don't free below */ } - buffer_free(&b); + sshbuf_free(b); free(sig); + auth2_record_key(authctxt, authenticated, key); } else { debug("%s: test whether pkalg/pkblob are acceptable for %s %s", __func__, sshkey_type(key), fp); - packet_check_eom(); + if ((r = sshpkt_get_end(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); /* XXX fake reply and always send PK_OK ? */ /* @@ -199,11 +219,13 @@ userauth_pubkey(Authctxt *authctxt) * issue? -markus */ if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) { - packet_start(SSH2_MSG_USERAUTH_PK_OK); - packet_put_string(pkalg, alen); - packet_put_string(pkblob, blen); - packet_send(); - packet_write_wait(); + if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_PK_OK)) + != 0 || + (r = sshpkt_put_cstring(ssh, pkalg)) != 0 || + (r = sshpkt_put_string(ssh, pkblob, blen)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("%s: %s", __func__, ssh_err(r)); + ssh_packet_write_wait(ssh); authctxt->postponed = 1; } } @@ -211,333 +233,14 @@ userauth_pubkey(Authctxt *authctxt) auth_clear_options(); done: debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg); - if (key != NULL) - key_free(key); + sshkey_free(key); + free(userstyle); free(pkalg); free(pkblob); free(fp); return authenticated; } -void -pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) -{ - char *fp, *extra; - va_list ap; - int i; - - extra = NULL; - if (fmt != NULL) { - va_start(ap, fmt); - i = vasprintf(&extra, fmt, ap); - va_end(ap); - if (i < 0 || extra == NULL) - fatal("%s: vasprintf failed", __func__); - } - - if (key_is_cert(key)) { - fp = sshkey_fingerprint(key->cert->signature_key, - options.fingerprint_hash, SSH_FP_DEFAULT); - auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", - key_type(key), key->cert->key_id, - (unsigned long long)key->cert->serial, - key_type(key->cert->signature_key), - fp == NULL ? "(null)" : fp, - extra == NULL ? "" : ", ", extra == NULL ? "" : extra); - free(fp); - } else { - fp = sshkey_fingerprint(key, options.fingerprint_hash, - SSH_FP_DEFAULT); - auth_info(authctxt, "%s %s%s%s", key_type(key), - fp == NULL ? "(null)" : fp, - extra == NULL ? "" : ", ", extra == NULL ? "" : extra); - free(fp); - } - free(extra); -} - -/* - * Splits 's' into an argument vector. Handles quoted string and basic - * escape characters (\\, \", \'). Caller must free the argument vector - * and its members. - */ -static int -split_argv(const char *s, int *argcp, char ***argvp) -{ - int r = SSH_ERR_INTERNAL_ERROR; - int argc = 0, quote, i, j; - char *arg, **argv = xcalloc(1, sizeof(*argv)); - - *argvp = NULL; - *argcp = 0; - - for (i = 0; s[i] != '\0'; i++) { - /* Skip leading whitespace */ - if (s[i] == ' ' || s[i] == '\t') - continue; - - /* Start of a token */ - quote = 0; - if (s[i] == '\\' && - (s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\')) - i++; - else if (s[i] == '\'' || s[i] == '"') - quote = s[i++]; - - argv = xreallocarray(argv, (argc + 2), sizeof(*argv)); - arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1); - argv[argc] = NULL; - - /* Copy the token in, removing escapes */ - for (j = 0; s[i] != '\0'; i++) { - if (s[i] == '\\') { - if (s[i + 1] == '\'' || - s[i + 1] == '\"' || - s[i + 1] == '\\') { - i++; /* Skip '\' */ - arg[j++] = s[i]; - } else { - /* Unrecognised escape */ - arg[j++] = s[i]; - } - } else if (quote == 0 && (s[i] == ' ' || s[i] == '\t')) - break; /* done */ - else if (quote != 0 && s[i] == quote) - break; /* done */ - else - arg[j++] = s[i]; - } - if (s[i] == '\0') { - if (quote != 0) { - /* Ran out of string looking for close quote */ - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - break; - } - } - /* Success */ - *argcp = argc; - *argvp = argv; - argc = 0; - argv = NULL; - r = 0; - out: - if (argc != 0 && argv != NULL) { - for (i = 0; i < argc; i++) - free(argv[i]); - free(argv); - } - return r; -} - -/* - * Reassemble an argument vector into a string, quoting and escaping as - * necessary. Caller must free returned string. - */ -static char * -assemble_argv(int argc, char **argv) -{ - int i, j, ws, r; - char c, *ret; - struct sshbuf *buf, *arg; - - if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); - - for (i = 0; i < argc; i++) { - ws = 0; - sshbuf_reset(arg); - for (j = 0; argv[i][j] != '\0'; j++) { - r = 0; - c = argv[i][j]; - switch (c) { - case ' ': - case '\t': - ws = 1; - r = sshbuf_put_u8(arg, c); - break; - case '\\': - case '\'': - case '"': - if ((r = sshbuf_put_u8(arg, '\\')) != 0) - break; - /* FALLTHROUGH */ - default: - r = sshbuf_put_u8(arg, c); - break; - } - if (r != 0) - fatal("%s: sshbuf_put_u8: %s", - __func__, ssh_err(r)); - } - if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) || - (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) || - (r = sshbuf_putb(buf, arg)) != 0 || - (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0)) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - } - if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL) - fatal("%s: malloc failed", __func__); - memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf)); - ret[sshbuf_len(buf)] = '\0'; - sshbuf_free(buf); - sshbuf_free(arg); - return ret; -} - -/* - * Runs command in a subprocess. Returns pid on success and a FILE* to the - * subprocess' stdout or 0 on failure. - * NB. "command" is only used for logging. - */ -static pid_t -subprocess(const char *tag, struct passwd *pw, const char *command, - int ac, char **av, FILE **child) -{ - FILE *f; - struct stat st; - int devnull, p[2], i; - pid_t pid; - char *cp, errmsg[512]; - u_int envsize; - char **child_env; - - *child = NULL; - - debug3("%s: %s command \"%s\" running as %s", __func__, - tag, command, pw->pw_name); - - /* Verify the path exists and is safe-ish to execute */ - if (*av[0] != '/') { - error("%s path is not absolute", tag); - return 0; - } - temporarily_use_uid(pw); - if (stat(av[0], &st) < 0) { - error("Could not stat %s \"%s\": %s", tag, - av[0], strerror(errno)); - restore_uid(); - return 0; - } - if (auth_secure_path(av[0], &st, NULL, 0, - errmsg, sizeof(errmsg)) != 0) { - error("Unsafe %s \"%s\": %s", tag, av[0], errmsg); - restore_uid(); - return 0; - } - - /* - * Run the command; stderr is left in place, stdout is the - * authorized_keys output. - */ - if (pipe(p) != 0) { - error("%s: pipe: %s", tag, strerror(errno)); - restore_uid(); - return 0; - } - - /* - * Don't want to call this in the child, where it can fatal() and - * run cleanup_exit() code. - */ - restore_uid(); - - switch ((pid = fork())) { - case -1: /* error */ - error("%s: fork: %s", tag, strerror(errno)); - close(p[0]); - close(p[1]); - return 0; - case 0: /* child */ - /* Prepare a minimal environment for the child. */ - envsize = 5; - child_env = xcalloc(sizeof(*child_env), envsize); - child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH); - child_set_env(&child_env, &envsize, "USER", pw->pw_name); - child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name); - child_set_env(&child_env, &envsize, "HOME", pw->pw_dir); - if ((cp = getenv("LANG")) != NULL) - child_set_env(&child_env, &envsize, "LANG", cp); - - for (i = 0; i < NSIG; i++) - signal(i, SIG_DFL); - - if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { - error("%s: open %s: %s", tag, _PATH_DEVNULL, - strerror(errno)); - _exit(1); - } - /* Keep stderr around a while longer to catch errors */ - if (dup2(devnull, STDIN_FILENO) == -1 || - dup2(p[1], STDOUT_FILENO) == -1) { - error("%s: dup2: %s", tag, strerror(errno)); - _exit(1); - } - closefrom(STDERR_FILENO + 1); - - /* Don't use permanently_set_uid() here to avoid fatal() */ - if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) { - error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid, - strerror(errno)); - _exit(1); - } - if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) { - error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid, - strerror(errno)); - _exit(1); - } - /* stdin is pointed to /dev/null at this point */ - if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) { - error("%s: dup2: %s", tag, strerror(errno)); - _exit(1); - } - - execve(av[0], av, child_env); - error("%s exec \"%s\": %s", tag, command, strerror(errno)); - _exit(127); - default: /* parent */ - break; - } - - close(p[1]); - if ((f = fdopen(p[0], "r")) == NULL) { - error("%s: fdopen: %s", tag, strerror(errno)); - close(p[0]); - /* Don't leave zombie child */ - kill(pid, SIGTERM); - while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) - ; - return 0; - } - /* Success */ - debug3("%s: %s pid %ld", __func__, tag, (long)pid); - *child = f; - return pid; -} - -/* Returns 0 if pid exited cleanly, non-zero otherwise */ -static int -exited_cleanly(pid_t pid, const char *tag, const char *cmd) -{ - int status; - - while (waitpid(pid, &status, 0) == -1) { - if (errno != EINTR) { - error("%s: waitpid: %s", tag, strerror(errno)); - return -1; - } - } - if (WIFSIGNALED(status)) { - error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status)); - return -1; - } else if (WEXITSTATUS(status) != 0) { - error("%s %s failed, status %d", tag, cmd, WEXITSTATUS(status)); - return -1; - } - return 0; -} - static int match_principals_option(const char *principal_list, struct sshkey_cert *cert) { @@ -559,7 +262,7 @@ match_principals_option(const char *principal_list, struct sshkey_cert *cert) } static int -process_principals(FILE *f, char *file, struct passwd *pw, +process_principals(FILE *f, const char *file, struct passwd *pw, const struct sshkey_cert *cert) { char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts; @@ -597,8 +300,7 @@ process_principals(FILE *f, char *file, struct passwd *pw, for (i = 0; i < cert->nprincipals; i++) { if (strcmp(cp, cert->principals[i]) == 0) { debug3("%s:%lu: matched principal \"%.100s\"", - file == NULL ? "(command)" : file, - linenum, cert->principals[i]); + file, linenum, cert->principals[i]); if (auth_parse_options(pw, line_opts, file, linenum) != 1) continue; @@ -671,7 +373,7 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key) } /* Turn the command into an argument vector */ - if (split_argv(options.authorized_principals_command, &ac, &av) != 0) { + if (argv_split(options.authorized_principals_command, &ac, &av) != 0) { error("AuthorizedPrincipalsCommand \"%s\" contains " "invalid quotes", command); goto out; @@ -720,21 +422,22 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key) av[i] = tmp; } /* Prepare a printable command for logs, etc. */ - command = assemble_argv(ac, av); + command = argv_assemble(ac, av); if ((pid = subprocess("AuthorizedPrincipalsCommand", pw, command, - ac, av, &f)) == 0) + ac, av, &f, + SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0) goto out; uid_swapped = 1; temporarily_use_uid(pw); - ok = process_principals(f, NULL, pw, cert); + ok = process_principals(f, "(command)", pw, cert); fclose(f); f = NULL; - if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command) != 0) + if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command, 0) != 0) goto out; /* Read completed successfully */ @@ -761,26 +464,25 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key) * returns 1 if the key is allowed or 0 otherwise. */ static int -check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) +check_authkeys_file(FILE *f, char *file, struct sshkey *key, struct passwd *pw) { char line[SSH_MAX_PUBKEY_BYTES]; int found_key = 0; u_long linenum = 0; - Key *found; + struct sshkey *found = NULL; - found_key = 0; - - found = NULL; while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { char *cp, *key_options = NULL, *fp = NULL; const char *reason = NULL; - /* Always consume entrire file */ + /* Always consume entire file */ if (found_key) continue; if (found != NULL) - key_free(found); - found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); + sshkey_free(found); + found = sshkey_new(sshkey_is_cert(key) ? KEY_UNSPEC : key->type); + if (found == NULL) + goto done; auth_clear_options(); /* Skip leading whitespace, empty and comment lines. */ @@ -789,7 +491,7 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) if (!*cp || *cp == '\n' || *cp == '#') continue; - if (key_read(found, &cp) != 1) { + if (sshkey_read(found, &cp) != 0) { /* no key? check if there are options for this key */ int quoted = 0; debug2("user_key_allowed: check options: '%s'", cp); @@ -803,14 +505,14 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) /* Skip remaining whitespace. */ for (; *cp == ' ' || *cp == '\t'; cp++) ; - if (key_read(found, &cp) != 1) { + if (sshkey_read(found, &cp) != 0) { debug2("user_key_allowed: advance: '%s'", cp); /* still no key? advance to next line*/ continue; } } - if (key_is_cert(key)) { - if (!key_equal(found, key->cert->signature_key)) + if (sshkey_is_cert(key)) { + if (!sshkey_equal(found, key->cert->signature_key)) continue; if (auth_parse_options(pw, key_options, file, linenum) != 1) @@ -821,7 +523,7 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) continue; debug("matching CA found: file %s, line %lu, %s %s", - file, linenum, key_type(found), fp); + file, linenum, sshkey_type(found), fp); /* * If the user has specified a list of principals as * a key option, then prefer that list to matching @@ -838,7 +540,7 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) auth_debug_add("%s", reason); continue; } - if (key_cert_check_authority(key, 0, 0, + if (sshkey_cert_check_authority(key, 0, 0, authorized_principals == NULL ? pw->pw_name : NULL, &reason) != 0) goto fail_reason; @@ -847,11 +549,11 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) verbose("Accepted certificate ID \"%s\" (serial %llu) " "signed by %s CA %s via %s", key->cert->key_id, (unsigned long long)key->cert->serial, - key_type(found), fp, file); + sshkey_type(found), fp, file); free(fp); found_key = 1; break; - } else if (key_equal(found, key)) { + } else if (sshkey_equal(found, key)) { if (auth_parse_options(pw, key_options, file, linenum) != 1) continue; @@ -861,14 +563,15 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) continue; debug("matching key found: file %s, line %lu %s %s", - file, linenum, key_type(found), fp); + file, linenum, sshkey_type(found), fp); free(fp); found_key = 1; continue; } } + done: if (found != NULL) - key_free(found); + sshkey_free(found); if (!found_key) debug2("key not found"); return found_key; @@ -876,24 +579,24 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw) /* Authenticate a certificate key against TrustedUserCAKeys */ static int -user_cert_trusted_ca(struct passwd *pw, Key *key) +user_cert_trusted_ca(struct passwd *pw, struct sshkey *key) { char *ca_fp, *principals_file = NULL; const char *reason; - int ret = 0, found_principal = 0, use_authorized_principals; + int r, ret = 0, found_principal = 0, use_authorized_principals; - if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL) + if (!sshkey_is_cert(key) || options.trusted_user_ca_keys == NULL) return 0; if ((ca_fp = sshkey_fingerprint(key->cert->signature_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) return 0; - if (sshkey_in_file(key->cert->signature_key, - options.trusted_user_ca_keys, 1, 0) != 0) { - debug2("%s: CA %s %s is not listed in %s", __func__, - key_type(key->cert->signature_key), ca_fp, - options.trusted_user_ca_keys); + if ((r = sshkey_in_file(key->cert->signature_key, + options.trusted_user_ca_keys, 1, 0)) != 0) { + debug2("%s: CA %s %s is not listed in %s: %s", __func__, + sshkey_type(key->cert->signature_key), ca_fp, + options.trusted_user_ca_keys, ssh_err(r)); goto out; } /* @@ -918,7 +621,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) auth_debug_add("%s", reason); goto out; } - if (key_cert_check_authority(key, 0, 1, + if (sshkey_cert_check_authority(key, 0, 1, use_authorized_principals ? NULL : pw->pw_name, &reason) != 0) goto fail_reason; if (auth_cert_options(key, pw, &reason) != 0) @@ -927,7 +630,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) verbose("Accepted certificate ID \"%s\" (serial %llu) signed by " "%s CA %s via %s", key->cert->key_id, (unsigned long long)key->cert->serial, - key_type(key->cert->signature_key), ca_fp, + sshkey_type(key->cert->signature_key), ca_fp, options.trusted_user_ca_keys); ret = 1; @@ -942,7 +645,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) * returns 1 if the key is allowed or 0 otherwise. */ static int -user_key_allowed2(struct passwd *pw, Key *key, char *file) +user_key_allowed2(struct passwd *pw, struct sshkey *key, char *file) { FILE *f; int found_key = 0; @@ -965,7 +668,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) * returns 1 if the key is allowed or 0 otherwise. */ static int -user_key_command_allowed2(struct passwd *user_pw, Key *key) +user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key) { FILE *f = NULL; int r, ok, found_key = 0; @@ -1011,7 +714,7 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key) } /* Turn the command into an argument vector */ - if (split_argv(options.authorized_keys_command, &ac, &av) != 0) { + if (argv_split(options.authorized_keys_command, &ac, &av) != 0) { error("AuthorizedKeysCommand \"%s\" contains invalid quotes", command); goto out; @@ -1035,7 +738,7 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key) av[i] = tmp; } /* Prepare a printable command for logs, etc. */ - command = assemble_argv(ac, av); + command = argv_assemble(ac, av); /* * If AuthorizedKeysCommand was run without arguments @@ -1052,7 +755,8 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key) } if ((pid = subprocess("AuthorizedKeysCommand", pw, command, - ac, av, &f)) == 0) + ac, av, &f, + SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0) goto out; uid_swapped = 1; @@ -1063,7 +767,7 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key) fclose(f); f = NULL; - if (exited_cleanly(pid, "AuthorizedKeysCommand", command) != 0) + if (exited_cleanly(pid, "AuthorizedKeysCommand", command, 0) != 0) goto out; /* Read completed successfully */ @@ -1088,14 +792,15 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key) * Check whether key authenticates and authorises the user. */ int -user_key_allowed(struct passwd *pw, Key *key, int auth_attempt) +user_key_allowed(struct passwd *pw, struct sshkey *key, int auth_attempt) { u_int success, i; char *file; if (auth_key_is_revoked(key)) return 0; - if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key)) + if (sshkey_is_cert(key) && + auth_key_is_revoked(key->cert->signature_key)) return 0; success = user_cert_trusted_ca(pw, key); @@ -1120,35 +825,6 @@ user_key_allowed(struct passwd *pw, Key *key, int auth_attempt) return success; } -/* Records a public key in the list of previously-successful keys */ -void -auth2_record_userkey(Authctxt *authctxt, struct sshkey *key) -{ - struct sshkey **tmp; - - if (authctxt->nprev_userkeys >= INT_MAX || - (tmp = reallocarray(authctxt->prev_userkeys, - authctxt->nprev_userkeys + 1, sizeof(*tmp))) == NULL) - fatal("%s: reallocarray failed", __func__); - authctxt->prev_userkeys = tmp; - authctxt->prev_userkeys[authctxt->nprev_userkeys] = key; - authctxt->nprev_userkeys++; -} - -/* Checks whether a key has already been used successfully for authentication */ -int -auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key) -{ - u_int i; - - for (i = 0; i < authctxt->nprev_userkeys; i++) { - if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) { - return 1; - } - } - return 0; -} - Authmethod method_pubkey = { "publickey", userauth_pubkey, diff --git a/auth2.c b/auth2.c index 97dd2ef0a4ff..862e09960b29 100644 --- a/auth2.c +++ b/auth2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2.c,v 1.137 2017/02/03 23:05:57 djm Exp $ */ +/* $OpenBSD: auth2.c,v 1.143 2017/06/24 06:34:38 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -55,6 +56,7 @@ #include "ssh-gss.h" #endif #include "monitor_wrap.h" +#include "ssherr.h" /* import */ extern ServerOptions options; @@ -87,8 +89,8 @@ Authmethod *authmethods[] = { /* protocol */ -static int input_service_request(int, u_int32_t, void *); -static int input_userauth_request(int, u_int32_t, void *); +static int input_service_request(int, u_int32_t, struct ssh *); +static int input_userauth_request(int, u_int32_t, struct ssh *); /* helper */ static Authmethod *authmethod_lookup(Authctxt *, const char *); @@ -168,16 +170,19 @@ userauth_banner(void) void do_authentication2(Authctxt *authctxt) { - dispatch_init(&dispatch_protocol_error); - dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); - dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); + struct ssh *ssh = active_state; /* XXX */ + ssh->authctxt = authctxt; /* XXX move to caller */ + ssh_dispatch_init(ssh, &dispatch_protocol_error); + ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request); + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success); + ssh->authctxt = NULL; } /*ARGSUSED*/ static int -input_service_request(int type, u_int32_t seq, void *ctxt) +input_service_request(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; u_int len; int acceptit = 0; char *service = packet_get_cstring(&len); @@ -190,7 +195,7 @@ input_service_request(int type, u_int32_t seq, void *ctxt) if (!authctxt->success) { acceptit = 1; /* now we can handle user-auth requests */ - dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); } } /* XXX all other service requests are denied */ @@ -210,10 +215,9 @@ input_service_request(int type, u_int32_t seq, void *ctxt) /*ARGSUSED*/ static int -input_userauth_request(int type, u_int32_t seq, void *ctxt) +input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = active_state; /* XXX */ - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Authmethod *m = NULL; char *user, *service, *method, *style = NULL; int authenticated = 0; @@ -267,14 +271,15 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) authctxt->user, authctxt->service, user, service); } /* reset state */ - auth2_challenge_stop(authctxt); + auth2_challenge_stop(ssh); #ifdef GSSAPI /* XXX move to auth2_gssapi_stop() */ - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); #endif + auth2_authctxt_reset_info(authctxt); authctxt->postponed = 0; authctxt->server_caused_failure = 0; @@ -282,9 +287,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) m = authmethod_lookup(authctxt, method); if (m != NULL && authctxt->failures < options.max_authtries) { debug2("input_userauth_request: try method %s", method); - authenticated = m->userauth(authctxt); + authenticated = m->userauth(ssh); } - userauth_finish(authctxt, authenticated, method, NULL); + userauth_finish(ssh, authenticated, method, NULL); free(service); free(user); @@ -293,10 +298,10 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) } void -userauth_finish(Authctxt *authctxt, int authenticated, const char *method, +userauth_finish(struct ssh *ssh, int authenticated, const char *method, const char *submethod) { - struct ssh *ssh = active_state; /* XXX */ + Authctxt *authctxt = ssh->authctxt; char *methods; int partial = 0; @@ -325,6 +330,10 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, /* Log before sending the reply */ auth_log(authctxt, authenticated, partial, method, submethod); + /* Update information exposed to session */ + if (authenticated || partial) + auth2_update_session_info(authctxt, method, submethod); + if (authctxt->postponed) return; @@ -352,7 +361,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, if (authenticated == 1) { /* turn off userauth */ - dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); packet_start(SSH2_MSG_USERAUTH_SUCCESS); packet_send(); packet_write_wait(); @@ -622,4 +631,128 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method, return 0; } +/* Reset method-specific information */ +void auth2_authctxt_reset_info(Authctxt *authctxt) +{ + sshkey_free(authctxt->auth_method_key); + free(authctxt->auth_method_info); + authctxt->auth_method_key = NULL; + authctxt->auth_method_info = NULL; +} + +/* Record auth method-specific information for logs */ +void +auth2_record_info(Authctxt *authctxt, const char *fmt, ...) +{ + va_list ap; + int i; + + free(authctxt->auth_method_info); + authctxt->auth_method_info = NULL; + + va_start(ap, fmt); + i = vasprintf(&authctxt->auth_method_info, fmt, ap); + va_end(ap); + + if (i < 0 || authctxt->auth_method_info == NULL) + fatal("%s: vasprintf failed", __func__); +} + +/* + * Records a public key used in authentication. This is used for logging + * and to ensure that the same key is not subsequently accepted again for + * multiple authentication. + */ +void +auth2_record_key(Authctxt *authctxt, int authenticated, + const struct sshkey *key) +{ + struct sshkey **tmp, *dup; + int r; + + if ((r = sshkey_demote(key, &dup)) != 0) + fatal("%s: copy key: %s", __func__, ssh_err(r)); + sshkey_free(authctxt->auth_method_key); + authctxt->auth_method_key = dup; + + if (!authenticated) + return; + + /* If authenticated, make sure we don't accept this key again */ + if ((r = sshkey_demote(key, &dup)) != 0) + fatal("%s: copy key: %s", __func__, ssh_err(r)); + if (authctxt->nprev_keys >= INT_MAX || + (tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys, + authctxt->nprev_keys + 1, sizeof(*authctxt->prev_keys))) == NULL) + fatal("%s: reallocarray failed", __func__); + authctxt->prev_keys = tmp; + authctxt->prev_keys[authctxt->nprev_keys] = dup; + authctxt->nprev_keys++; + +} + +/* Checks whether a key has already been previously used for authentication */ +int +auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key) +{ + u_int i; + char *fp; + + for (i = 0; i < authctxt->nprev_keys; i++) { + if (sshkey_equal_public(key, authctxt->prev_keys[i])) { + fp = sshkey_fingerprint(authctxt->prev_keys[i], + options.fingerprint_hash, SSH_FP_DEFAULT); + debug3("%s: key already used: %s %s", __func__, + sshkey_type(authctxt->prev_keys[i]), + fp == NULL ? "UNKNOWN" : fp); + free(fp); + return 1; + } + } + return 0; +} + +/* + * Updates authctxt->session_info with details of authentication. Should be + * whenever an authentication method succeeds. + */ +void +auth2_update_session_info(Authctxt *authctxt, const char *method, + const char *submethod) +{ + int r; + + if (authctxt->session_info == NULL) { + if ((authctxt->session_info = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new", __func__); + } + + /* Append method[/submethod] */ + if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s", + method, submethod == NULL ? "" : "/", + submethod == NULL ? "" : submethod)) != 0) + fatal("%s: append method: %s", __func__, ssh_err(r)); + + /* Append key if present */ + if (authctxt->auth_method_key != NULL) { + if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 || + (r = sshkey_format_text(authctxt->auth_method_key, + authctxt->session_info)) != 0) + fatal("%s: append key: %s", __func__, ssh_err(r)); + } + + if (authctxt->auth_method_info != NULL) { + /* Ensure no ambiguity here */ + if (strchr(authctxt->auth_method_info, '\n') != NULL) + fatal("%s: auth_method_info contains \\n", __func__); + if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 || + (r = sshbuf_putf(authctxt->session_info, "%s", + authctxt->auth_method_info)) != 0) { + fatal("%s: append method info: %s", + __func__, ssh_err(r)); + } + } + if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0) + fatal("%s: append: %s", __func__, ssh_err(r)); +} diff --git a/authfd.c b/authfd.c index a634bcb81c58..a460fa350c8a 100644 --- a/authfd.c +++ b/authfd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.c,v 1.100 2015/12/04 16:41:28 markus Exp $ */ +/* $OpenBSD: authfd.c,v 1.105 2017/07/01 13:50:45 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -51,7 +51,6 @@ #include "xmalloc.h" #include "ssh.h" -#include "rsa.h" #include "sshbuf.h" #include "sshkey.h" #include "authfd.h" @@ -199,43 +198,6 @@ ssh_lock_agent(int sock, int lock, const char *password) return r; } -#ifdef WITH_SSH1 -static int -deserialise_identity1(struct sshbuf *ids, struct sshkey **keyp, char **commentp) -{ - struct sshkey *key; - int r, keybits; - u_int32_t bits; - char *comment = NULL; - - if ((key = sshkey_new(KEY_RSA1)) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_get_u32(ids, &bits)) != 0 || - (r = sshbuf_get_bignum1(ids, key->rsa->e)) != 0 || - (r = sshbuf_get_bignum1(ids, key->rsa->n)) != 0 || - (r = sshbuf_get_cstring(ids, &comment, NULL)) != 0) - goto out; - keybits = BN_num_bits(key->rsa->n); - /* XXX previously we just warned here. I think we should be strict */ - if (keybits < 0 || bits != (u_int)keybits) { - r = SSH_ERR_KEY_BITS_MISMATCH; - goto out; - } - if (keyp != NULL) { - *keyp = key; - key = NULL; - } - if (commentp != NULL) { - *commentp = comment; - comment = NULL; - } - r = 0; - out: - sshkey_free(key); - free(comment); - return r; -} -#endif static int deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp) @@ -264,35 +226,21 @@ deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp) * Fetch list of identities held by the agent. */ int -ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp) +ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp) { - u_char type, code1 = 0, code2 = 0; + u_char type; u_int32_t num, i; struct sshbuf *msg; struct ssh_identitylist *idl = NULL; int r; - /* Determine request and expected response types */ - switch (version) { - case 1: - code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; - code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER; - break; - case 2: - code1 = SSH2_AGENTC_REQUEST_IDENTITIES; - code2 = SSH2_AGENT_IDENTITIES_ANSWER; - break; - default: - return SSH_ERR_INVALID_ARGUMENT; - } - /* * Send a message to the agent requesting for a list of the * identities it can represent. */ if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_u8(msg, code1)) != 0) + if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_REQUEST_IDENTITIES)) != 0) goto out; if ((r = ssh_request_reply(sock, msg, msg)) != 0) @@ -304,7 +252,7 @@ ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp) if (agent_failed(type)) { r = SSH_ERR_AGENT_FAILURE; goto out; - } else if (type != code2) { + } else if (type != SSH2_AGENT_IDENTITIES_ANSWER) { r = SSH_ERR_INVALID_FORMAT; goto out; } @@ -329,25 +277,14 @@ ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp) goto out; } for (i = 0; i < num;) { - switch (version) { - case 1: -#ifdef WITH_SSH1 - if ((r = deserialise_identity1(msg, - &(idl->keys[i]), &(idl->comments[i]))) != 0) + if ((r = deserialise_identity2(msg, &(idl->keys[i]), + &(idl->comments[i]))) != 0) { + if (r == SSH_ERR_KEY_TYPE_UNKNOWN) { + /* Gracefully skip unknown key types */ + num--; + continue; + } else goto out; -#endif - break; - case 2: - if ((r = deserialise_identity2(msg, - &(idl->keys[i]), &(idl->comments[i]))) != 0) { - if (r == SSH_ERR_KEY_TYPE_UNKNOWN) { - /* Gracefully skip unknown key types */ - num--; - continue; - } else - goto out; - } - break; } i++; } @@ -385,50 +322,10 @@ ssh_free_identitylist(struct ssh_identitylist *idl) * otherwise. */ -#ifdef WITH_SSH1 -int -ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge, - u_char session_id[16], u_char response[16]) -{ - struct sshbuf *msg; - int r; - u_char type; - - if (key->type != KEY_RSA1) - return SSH_ERR_INVALID_ARGUMENT; - if ((msg = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_put_u8(msg, SSH_AGENTC_RSA_CHALLENGE)) != 0 || - (r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 || - (r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 || - (r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0 || - (r = sshbuf_put_bignum1(msg, challenge)) != 0 || - (r = sshbuf_put(msg, session_id, 16)) != 0 || - (r = sshbuf_put_u32(msg, 1)) != 0) /* Response type for proto 1.1 */ - goto out; - if ((r = ssh_request_reply(sock, msg, msg)) != 0) - goto out; - if ((r = sshbuf_get_u8(msg, &type)) != 0) - goto out; - if (agent_failed(type)) { - r = SSH_ERR_AGENT_FAILURE; - goto out; - } else if (type != SSH_AGENT_RSA_RESPONSE) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((r = sshbuf_get(msg, response, 16)) != 0) - goto out; - r = 0; - out: - sshbuf_free(msg); - return r; -} -#endif /* encode signature algoritm in flag bits, so we can keep the msg format */ static u_int -agent_encode_alg(struct sshkey *key, const char *alg) +agent_encode_alg(const struct sshkey *key, const char *alg) { if (alg != NULL && key->type == KEY_RSA) { if (strcmp(alg, "rsa-sha2-256") == 0) @@ -441,7 +338,7 @@ agent_encode_alg(struct sshkey *key, const char *alg) /* ask agent to sign data, returns err.h code on error, 0 on success */ int -ssh_agent_sign(int sock, struct sshkey *key, +ssh_agent_sign(int sock, const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, u_int compat) { @@ -494,25 +391,6 @@ ssh_agent_sign(int sock, struct sshkey *key, /* Encode key for a message to the agent. */ -#ifdef WITH_SSH1 -static int -ssh_encode_identity_rsa1(struct sshbuf *b, RSA *key, const char *comment) -{ - int r; - - /* To keep within the protocol: p < q for ssh. in SSL p > q */ - if ((r = sshbuf_put_u32(b, BN_num_bits(key->n))) != 0 || - (r = sshbuf_put_bignum1(b, key->n)) != 0 || - (r = sshbuf_put_bignum1(b, key->e)) != 0 || - (r = sshbuf_put_bignum1(b, key->d)) != 0 || - (r = sshbuf_put_bignum1(b, key->iqmp)) != 0 || - (r = sshbuf_put_bignum1(b, key->q)) != 0 || - (r = sshbuf_put_bignum1(b, key->p)) != 0 || - (r = sshbuf_put_cstring(b, comment)) != 0) - return r; - return 0; -} -#endif static int ssh_encode_identity_ssh2(struct sshbuf *b, struct sshkey *key, @@ -561,16 +439,6 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment, return SSH_ERR_ALLOC_FAIL; switch (key->type) { -#ifdef WITH_SSH1 - case KEY_RSA1: - type = constrained ? - SSH_AGENTC_ADD_RSA_ID_CONSTRAINED : - SSH_AGENTC_ADD_RSA_IDENTITY; - if ((r = sshbuf_put_u8(msg, type)) != 0 || - (r = ssh_encode_identity_rsa1(msg, key->rsa, comment)) != 0) - goto out; - break; -#endif #ifdef WITH_OPENSSL case KEY_RSA: case KEY_RSA_CERT: @@ -620,16 +488,6 @@ ssh_remove_identity(int sock, struct sshkey *key) if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; -#ifdef WITH_SSH1 - if (key->type == KEY_RSA1) { - if ((r = sshbuf_put_u8(msg, - SSH_AGENTC_REMOVE_RSA_IDENTITY)) != 0 || - (r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 || - (r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 || - (r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0) - goto out; - } else -#endif if (key->type != KEY_UNSPEC) { if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) goto out; @@ -696,6 +554,10 @@ ssh_update_card(int sock, int add, const char *reader_id, const char *pin, /* * Removes all identities from the agent. * This call is intended only for use by ssh-add(1) and like applications. + * + * This supports the SSH protocol 1 message to because, when clearing all + * keys from an agent, we generally want to clear both protocol v1 and v2 + * keys. */ int ssh_remove_all_identities(int sock, int version) diff --git a/authfd.h b/authfd.h index 4b417e3f4a22..43abf85dadfe 100644 --- a/authfd.h +++ b/authfd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.h,v 1.39 2015/12/04 16:41:28 markus Exp $ */ +/* $OpenBSD: authfd.h,v 1.41 2017/06/28 01:09:22 djm Exp $ */ /* * Author: Tatu Ylonen @@ -27,8 +27,7 @@ int ssh_get_authentication_socket(int *fdp); void ssh_close_authentication_socket(int sock); int ssh_lock_agent(int sock, int lock, const char *password); -int ssh_fetch_identitylist(int sock, int version, - struct ssh_identitylist **idlp); +int ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp); void ssh_free_identitylist(struct ssh_identitylist *idl); int ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment, u_int life, u_int confirm); @@ -39,7 +38,7 @@ int ssh_remove_all_identities(int sock, int version); int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge, u_char session_id[16], u_char response[16]); -int ssh_agent_sign(int sock, struct sshkey *key, +int ssh_agent_sign(int sock, const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, u_int compat); diff --git a/authfile.c b/authfile.c index 7411b68f6e42..d09b700d21d9 100644 --- a/authfile.c +++ b/authfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authfile.c,v 1.122 2016/11/25 23:24:45 djm Exp $ */ +/* $OpenBSD: authfile.c,v 1.127 2017/07/01 13:50:45 djm Exp $ */ /* * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. * @@ -42,7 +42,6 @@ #include "ssh.h" #include "log.h" #include "authfile.h" -#include "rsa.h" #include "misc.h" #include "atomicio.h" #include "sshkey.h" @@ -100,25 +99,13 @@ sshkey_load_file(int fd, struct sshbuf *blob) u_char buf[1024]; size_t len; struct stat st; - int r, dontmax = 0; + int r; if (fstat(fd, &st) < 0) return SSH_ERR_SYSTEM_ERROR; if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && st.st_size > MAX_KEY_FILE_SIZE) return SSH_ERR_INVALID_FORMAT; - /* - * Pre-allocate the buffer used for the key contents and clamp its - * maximum size. This ensures that key contents are never leaked via - * implicit realloc() in the sshbuf code. - */ - if ((st.st_mode & S_IFREG) == 0 || st.st_size <= 0) { - st.st_size = 64*1024; /* 64k should be enough for anyone :) */ - dontmax = 1; - } - if ((r = sshbuf_allocate(blob, st.st_size)) != 0 || - (dontmax && (r = sshbuf_set_max_size(blob, st.st_size)) != 0)) - return r; for (;;) { if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { if (errno == EPIPE) @@ -147,35 +134,6 @@ sshkey_load_file(int fd, struct sshbuf *blob) return r; } -#ifdef WITH_SSH1 -/* - * Loads the public part of the ssh v1 key file. Returns NULL if an error was - * encountered (the file does not exist or is not readable), and the key - * otherwise. - */ -static int -sshkey_load_public_rsa1(int fd, struct sshkey **keyp, char **commentp) -{ - struct sshbuf *b = NULL; - int r; - - if (keyp != NULL) - *keyp = NULL; - if (commentp != NULL) - *commentp = NULL; - - if ((b = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshkey_load_file(fd, b)) != 0) - goto out; - if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0) - goto out; - r = 0; - out: - sshbuf_free(b); - return r; -} -#endif /* WITH_SSH1 */ /* XXX remove error() calls from here? */ int @@ -345,75 +303,48 @@ sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp) return SSH_ERR_INVALID_FORMAT; } -/* load public key from ssh v1 private or any pubkey file */ +/* load public key from any pubkey file */ int sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) { struct sshkey *pub = NULL; - char file[PATH_MAX]; - int r, fd; + char *file = NULL; + int r; if (keyp != NULL) *keyp = NULL; if (commentp != NULL) *commentp = NULL; - /* XXX should load file once and attempt to parse each format */ - - if ((fd = open(filename, O_RDONLY)) < 0) - goto skip; -#ifdef WITH_SSH1 - /* try rsa1 private key */ - r = sshkey_load_public_rsa1(fd, keyp, commentp); - close(fd); - switch (r) { - case SSH_ERR_INTERNAL_ERROR: - case SSH_ERR_ALLOC_FAIL: - case SSH_ERR_INVALID_ARGUMENT: - case SSH_ERR_SYSTEM_ERROR: - case 0: - return r; - } -#else /* WITH_SSH1 */ - close(fd); -#endif /* WITH_SSH1 */ - - /* try ssh2 public key */ if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) { - if (keyp != NULL) + if (keyp != NULL) { *keyp = pub; - return 0; + pub = NULL; + } + r = 0; + goto out; } sshkey_free(pub); -#ifdef WITH_SSH1 - /* try rsa1 public key */ - if ((pub = sshkey_new(KEY_RSA1)) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) { - if (keyp != NULL) - *keyp = pub; - return 0; - } - sshkey_free(pub); -#endif /* WITH_SSH1 */ - - skip: /* try .pub suffix */ - if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) + if (asprintf(&file, "%s.pub", filename) == -1) return SSH_ERR_ALLOC_FAIL; - r = SSH_ERR_ALLOC_FAIL; /* in case strlcpy or strlcat fail */ - if ((strlcpy(file, filename, sizeof file) < sizeof(file)) && - (strlcat(file, ".pub", sizeof file) < sizeof(file)) && - (r = sshkey_try_load_public(pub, file, commentp)) == 0) { - if (keyp != NULL) - *keyp = pub; - return 0; + if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; } + if ((r = sshkey_try_load_public(pub, file, commentp)) == 0) { + if (keyp != NULL) { + *keyp = pub; + pub = NULL; + } + r = 0; + } + out: + free(file); sshkey_free(pub); - return r; } diff --git a/bitmap.c b/bitmap.c index f95032250e7c..5089b04070e7 100644 --- a/bitmap.c +++ b/bitmap.c @@ -53,8 +53,9 @@ void bitmap_free(struct bitmap *b) { if (b != NULL && b->d != NULL) { - explicit_bzero(b->d, b->len); + bitmap_zero(b); free(b->d); + b->d = NULL; } free(b); } @@ -86,10 +87,10 @@ reserve(struct bitmap *b, u_int n) return -1; /* invalid */ nlen = (n / BITMAP_BITS) + 1; if (b->len < nlen) { - if ((tmp = reallocarray(b->d, nlen, BITMAP_BYTES)) == NULL) + if ((tmp = recallocarray(b->d, b->len, + nlen, BITMAP_BYTES)) == NULL) return -1; b->d = tmp; - memset(b->d + b->len, 0, (nlen - b->len) * BITMAP_BYTES); b->len = nlen; } return 0; @@ -188,7 +189,7 @@ bitmap_from_string(struct bitmap *b, const void *p, size_t l) { int r; size_t i, offset, shift; - u_char *s = (u_char *)p; + const u_char *s = (const u_char *)p; if (l > BITMAP_MAX / 8) return -1; diff --git a/bufbn.c b/bufbn.c index 33ae7f73fd9c..98f9466bc8a2 100644 --- a/bufbn.c +++ b/bufbn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bufbn.c,v 1.12 2014/04/30 05:29:56 djm Exp $ */ +/* $OpenBSD: bufbn.c,v 1.13 2017/04/30 23:23:54 djm Exp $ */ /* * Copyright (c) 2012 Damien Miller @@ -28,46 +28,6 @@ #include "log.h" #include "ssherr.h" -#ifdef WITH_SSH1 -int -buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value) -{ - int ret; - - if ((ret = sshbuf_put_bignum1(buffer, value)) != 0) { - error("%s: %s", __func__, ssh_err(ret)); - return -1; - } - return 0; -} - -void -buffer_put_bignum(Buffer *buffer, const BIGNUM *value) -{ - if (buffer_put_bignum_ret(buffer, value) == -1) - fatal("%s: buffer error", __func__); -} - -int -buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value) -{ - int ret; - - if ((ret = sshbuf_get_bignum1(buffer, value)) != 0) { - error("%s: %s", __func__, ssh_err(ret)); - return -1; - } - return 0; -} - -void -buffer_get_bignum(Buffer *buffer, BIGNUM *value) -{ - if (buffer_get_bignum_ret(buffer, value) == -1) - fatal("%s: buffer error", __func__); -} -#endif /* WITH_SSH1 */ - int buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value) { diff --git a/buffer.h b/buffer.h index df1aebc02cc6..56174394c959 100644 --- a/buffer.h +++ b/buffer.h @@ -1,4 +1,4 @@ -/* $OpenBSD: buffer.h,v 1.25 2014/04/30 05:29:56 djm Exp $ */ +/* $OpenBSD: buffer.h,v 1.26 2017/04/30 23:23:54 djm Exp $ */ /* * Copyright (c) 2012 Damien Miller @@ -49,9 +49,7 @@ int buffer_consume_end_ret(Buffer *, u_int); #include #include -void buffer_put_bignum(Buffer *, const BIGNUM *); void buffer_put_bignum2(Buffer *, const BIGNUM *); -void buffer_get_bignum(Buffer *, BIGNUM *); void buffer_get_bignum2(Buffer *, BIGNUM *); void buffer_put_bignum2_from_string(Buffer *, const u_char *, u_int); @@ -75,8 +73,6 @@ void buffer_put_cstring(Buffer *, const char *); #define buffer_skip_string(b) (void)buffer_get_string_ptr(b, NULL); -int buffer_put_bignum_ret(Buffer *, const BIGNUM *); -int buffer_get_bignum_ret(Buffer *, BIGNUM *); int buffer_put_bignum2_ret(Buffer *, const BIGNUM *); int buffer_get_bignum2_ret(Buffer *, BIGNUM *); int buffer_get_short_ret(u_short *, Buffer *); diff --git a/channels.c b/channels.c index d030fcdd9010..83442be06432 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.357 2017/02/01 02:59:09 dtucker Exp $ */ +/* $OpenBSD: channels.c,v 1.375 2017/09/24 13:45:34 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -55,27 +55,27 @@ #include #include +#include #include +#include #ifdef HAVE_STDINT_H -#include + #include #endif #include #include #include #include #include -#include #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" -#include "ssh1.h" #include "ssh2.h" #include "ssherr.h" +#include "sshbuf.h" #include "packet.h" #include "log.h" #include "misc.h" -#include "buffer.h" #include "channels.h" #include "compat.h" #include "canohost.h" @@ -83,28 +83,19 @@ #include "authfd.h" #include "pathnames.h" -/* -- channel core */ - -/* - * Pointer to an array containing all allocated channels. The array is - * dynamically extended as needed. - */ -static Channel **channels = NULL; - -/* - * Size of the channel array. All slots of the array must always be - * initialized (at least the type field); unused slots set to NULL - */ -static u_int channels_alloc = 0; - -/* - * Maximum file descriptor value used in any of the channels. This is - * updated in channel_new. - */ -static int channel_max_fd = 0; - +/* -- agent forwarding */ +#define NUM_SOCKS 10 /* -- tcp forwarding */ +/* special-case port number meaning allow any port */ +#define FWD_PERMIT_ANY_PORT 0 + +/* special-case wildcard meaning allow any host */ +#define FWD_PERMIT_ANY_HOST "*" + +/* -- X11 forwarding */ +/* Maximum number of fake X11 displays to try. */ +#define MAX_DISPLAYS 1000 /* * Data structure for storing which hosts are permitted for forward requests. @@ -124,101 +115,153 @@ typedef struct { Channel *downstream; /* Downstream mux*/ } ForwardPermission; -/* List of all permitted host/port pairs to connect by the user. */ -static ForwardPermission *permitted_opens = NULL; +typedef void chan_fn(struct ssh *, Channel *c, + fd_set *readset, fd_set *writeset); -/* List of all permitted host/port pairs to connect by the admin. */ -static ForwardPermission *permitted_adm_opens = NULL; +/* Master structure for channels state */ +struct ssh_channels { + /* + * Pointer to an array containing all allocated channels. The array + * is dynamically extended as needed. + */ + Channel **channels; -/* Number of permitted host/port pairs in the array permitted by the user. */ -static int num_permitted_opens = 0; + /* + * Size of the channel array. All slots of the array must always be + * initialized (at least the type field); unused slots set to NULL + */ + u_int channels_alloc; -/* Number of permitted host/port pair in the array permitted by the admin. */ -static int num_adm_permitted_opens = 0; + /* + * Maximum file descriptor value used in any of the channels. This is + * updated in channel_new. + */ + int channel_max_fd; -/* special-case port number meaning allow any port */ -#define FWD_PERMIT_ANY_PORT 0 + /* + * 'channel_pre*' are called just before select() to add any bits + * relevant to channels in the select bitmasks. + * + * 'channel_post*': perform any appropriate operations for + * channels which have events pending. + */ + chan_fn **channel_pre; + chan_fn **channel_post; -/* special-case wildcard meaning allow any host */ -#define FWD_PERMIT_ANY_HOST "*" + /* -- tcp forwarding */ -/* - * If this is true, all opens are permitted. This is the case on the server - * on which we have to trust the client anyway, and the user could do - * anything after logging in anyway. - */ -static int all_opens_permitted = 0; + /* List of all permitted host/port pairs to connect by the user. */ + ForwardPermission *permitted_opens; + /* List of all permitted host/port pairs to connect by the admin. */ + ForwardPermission *permitted_adm_opens; -/* -- X11 forwarding */ + /* + * Number of permitted host/port pairs in the array permitted by + * the user. + */ + u_int num_permitted_opens; -/* Maximum number of fake X11 displays to try. */ -#define MAX_DISPLAYS 1000 + /* + * Number of permitted host/port pair in the array permitted by + * the admin. + */ + u_int num_adm_permitted_opens; -/* Saved X11 local (client) display. */ -static char *x11_saved_display = NULL; + /* + * If this is true, all opens are permitted. This is the case on + * the server on which we have to trust the client anyway, and the + * user could do anything after logging in anyway. + */ + int all_opens_permitted; -/* Saved X11 authentication protocol name. */ -static char *x11_saved_proto = NULL; + /* -- X11 forwarding */ -/* Saved X11 authentication data. This is the real data. */ -static char *x11_saved_data = NULL; -static u_int x11_saved_data_len = 0; + /* Saved X11 local (client) display. */ + char *x11_saved_display; -/* Deadline after which all X11 connections are refused */ -static u_int x11_refuse_time; + /* Saved X11 authentication protocol name. */ + char *x11_saved_proto; -/* - * Fake X11 authentication data. This is what the server will be sending us; - * we should replace any occurrences of this by the real data. - */ -static u_char *x11_fake_data = NULL; -static u_int x11_fake_data_len; + /* Saved X11 authentication data. This is the real data. */ + char *x11_saved_data; + u_int x11_saved_data_len; + /* Deadline after which all X11 connections are refused */ + u_int x11_refuse_time; -/* -- agent forwarding */ + /* + * Fake X11 authentication data. This is what the server will be + * sending us; we should replace any occurrences of this by the + * real data. + */ + u_char *x11_fake_data; + u_int x11_fake_data_len; -#define NUM_SOCKS 10 - -/* AF_UNSPEC or AF_INET or AF_INET6 */ -static int IPv4or6 = AF_UNSPEC; + /* AF_UNSPEC or AF_INET or AF_INET6 */ + int IPv4or6; +}; /* helper */ -static void port_open_helper(Channel *c, char *rtype); +static void port_open_helper(struct ssh *ssh, Channel *c, char *rtype); static const char *channel_rfwd_bind_host(const char *listen_host); /* non-blocking connect helpers */ static int connect_next(struct channel_connect *); static void channel_connect_ctx_free(struct channel_connect *); +static Channel *rdynamic_connect_prepare(struct ssh *, char *, char *); +static int rdynamic_connect_finish(struct ssh *, Channel *); + +/* Setup helper */ +static void channel_handler_init(struct ssh_channels *sc); /* -- channel core */ +void +channel_init_channels(struct ssh *ssh) +{ + struct ssh_channels *sc; + + if ((sc = calloc(1, sizeof(*sc))) == NULL || + (sc->channel_pre = calloc(SSH_CHANNEL_MAX_TYPE, + sizeof(*sc->channel_pre))) == NULL || + (sc->channel_post = calloc(SSH_CHANNEL_MAX_TYPE, + sizeof(*sc->channel_post))) == NULL) + fatal("%s: allocation failed", __func__); + sc->channels_alloc = 10; + sc->channels = xcalloc(sc->channels_alloc, sizeof(*sc->channels)); + sc->IPv4or6 = AF_UNSPEC; + channel_handler_init(sc); + + ssh->chanctxt = sc; +} + Channel * -channel_by_id(int id) +channel_by_id(struct ssh *ssh, int id) { Channel *c; - if (id < 0 || (u_int)id >= channels_alloc) { - logit("channel_by_id: %d: bad id", id); + if (id < 0 || (u_int)id >= ssh->chanctxt->channels_alloc) { + logit("%s: %d: bad id", __func__, id); return NULL; } - c = channels[id]; + c = ssh->chanctxt->channels[id]; if (c == NULL) { - logit("channel_by_id: %d: bad id: channel free", id); + logit("%s: %d: bad id: channel free", __func__, id); return NULL; } return c; } Channel * -channel_by_remote_id(int remote_id) +channel_by_remote_id(struct ssh *ssh, u_int remote_id) { Channel *c; u_int i; - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; - if (c != NULL && c->remote_id == remote_id) + for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { + c = ssh->chanctxt->channels[i]; + if (c != NULL && c->have_remote_id && c->remote_id == remote_id) return c; } return NULL; @@ -229,28 +272,28 @@ channel_by_remote_id(int remote_id) * Private channels, like listening sockets, may not receive messages. */ Channel * -channel_lookup(int id) +channel_lookup(struct ssh *ssh, int id) { Channel *c; - if ((c = channel_by_id(id)) == NULL) - return (NULL); + if ((c = channel_by_id(ssh, id)) == NULL) + return NULL; switch (c->type) { case SSH_CHANNEL_X11_OPEN: case SSH_CHANNEL_LARVAL: case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_DYNAMIC: + case SSH_CHANNEL_RDYNAMIC_OPEN: + case SSH_CHANNEL_RDYNAMIC_FINISH: case SSH_CHANNEL_OPENING: case SSH_CHANNEL_OPEN: - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_MUX_PROXY: - return (c); + return c; } logit("Non-public channel %d, type %d.", id, c->type); - return (NULL); + return NULL; } /* @@ -258,13 +301,15 @@ channel_lookup(int id) * when the channel consumer/producer is ready, e.g. shell exec'd */ static void -channel_register_fds(Channel *c, int rfd, int wfd, int efd, +channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd, int extusage, int nonblock, int is_tty) { + struct ssh_channels *sc = ssh->chanctxt; + /* Update the maximum file descriptor value. */ - channel_max_fd = MAXIMUM(channel_max_fd, rfd); - channel_max_fd = MAXIMUM(channel_max_fd, wfd); - channel_max_fd = MAXIMUM(channel_max_fd, efd); + sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, rfd); + sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, wfd); + sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, efd); if (rfd != -1) fcntl(rfd, F_SETFD, FD_CLOEXEC); @@ -302,192 +347,220 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd, * remote_name to be freed. */ Channel * -channel_new(char *ctype, int type, int rfd, int wfd, int efd, +channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd, u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock) { - int found; - u_int i; + struct ssh_channels *sc = ssh->chanctxt; + u_int i, found; Channel *c; - /* Do initial allocation if this is the first call. */ - if (channels_alloc == 0) { - channels_alloc = 10; - channels = xcalloc(channels_alloc, sizeof(Channel *)); - for (i = 0; i < channels_alloc; i++) - channels[i] = NULL; - } /* Try to find a free slot where to put the new channel. */ - for (found = -1, i = 0; i < channels_alloc; i++) - if (channels[i] == NULL) { + for (i = 0; i < sc->channels_alloc; i++) { + if (sc->channels[i] == NULL) { /* Found a free slot. */ - found = (int)i; + found = i; break; } - if (found < 0) { - /* There are no free slots. Take last+1 slot and expand the array. */ - found = channels_alloc; - if (channels_alloc > 10000) - fatal("channel_new: internal error: channels_alloc %d " - "too big.", channels_alloc); - channels = xreallocarray(channels, channels_alloc + 10, - sizeof(Channel *)); - channels_alloc += 10; - debug2("channel: expanding %d", channels_alloc); - for (i = found; i < channels_alloc; i++) - channels[i] = NULL; + } + if (i >= sc->channels_alloc) { + /* + * There are no free slots. Take last+1 slot and expand + * the array. + */ + found = sc->channels_alloc; + if (sc->channels_alloc > CHANNELS_MAX_CHANNELS) + fatal("%s: internal error: channels_alloc %d too big", + __func__, sc->channels_alloc); + sc->channels = xrecallocarray(sc->channels, sc->channels_alloc, + sc->channels_alloc + 10, sizeof(*sc->channels)); + sc->channels_alloc += 10; + debug2("channel: expanding %d", sc->channels_alloc); } /* Initialize and return new channel. */ - c = channels[found] = xcalloc(1, sizeof(Channel)); - buffer_init(&c->input); - buffer_init(&c->output); - buffer_init(&c->extended); - c->path = NULL; - c->listening_addr = NULL; - c->listening_port = 0; + c = sc->channels[found] = xcalloc(1, sizeof(Channel)); + if ((c->input = sshbuf_new()) == NULL || + (c->output = sshbuf_new()) == NULL || + (c->extended = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); c->ostate = CHAN_OUTPUT_OPEN; c->istate = CHAN_INPUT_OPEN; - c->flags = 0; - channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, 0); - c->notbefore = 0; + channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, 0); c->self = found; c->type = type; c->ctype = ctype; c->local_window = window; c->local_window_max = window; - c->local_consumed = 0; c->local_maxpacket = maxpack; - c->remote_id = -1; c->remote_name = xstrdup(remote_name); - c->remote_window = 0; - c->remote_maxpacket = 0; - c->force_drain = 0; - c->single_connection = 0; - c->detach_user = NULL; - c->detach_close = 0; - c->open_confirm = NULL; - c->open_confirm_ctx = NULL; - c->input_filter = NULL; - c->output_filter = NULL; - c->filter_ctx = NULL; - c->filter_cleanup = NULL; c->ctl_chan = -1; - c->mux_rcb = NULL; - c->mux_ctx = NULL; - c->mux_pause = 0; c->delayed = 1; /* prevent call to channel_post handler */ TAILQ_INIT(&c->status_confirms); debug("channel %d: new [%s]", found, remote_name); return c; } -static int -channel_find_maxfd(void) +static void +channel_find_maxfd(struct ssh_channels *sc) { u_int i; int max = 0; Channel *c; - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; + for (i = 0; i < sc->channels_alloc; i++) { + c = sc->channels[i]; if (c != NULL) { max = MAXIMUM(max, c->rfd); max = MAXIMUM(max, c->wfd); max = MAXIMUM(max, c->efd); } } - return max; + sc->channel_max_fd = max; } int -channel_close_fd(int *fdp) +channel_close_fd(struct ssh *ssh, int *fdp) { + struct ssh_channels *sc = ssh->chanctxt; int ret = 0, fd = *fdp; if (fd != -1) { ret = close(fd); *fdp = -1; - if (fd == channel_max_fd) - channel_max_fd = channel_find_maxfd(); + if (fd == sc->channel_max_fd) + channel_find_maxfd(sc); } return ret; } /* Close all channel fd/socket. */ static void -channel_close_fds(Channel *c) +channel_close_fds(struct ssh *ssh, Channel *c) { - channel_close_fd(&c->sock); - channel_close_fd(&c->rfd); - channel_close_fd(&c->wfd); - channel_close_fd(&c->efd); + channel_close_fd(ssh, &c->sock); + channel_close_fd(ssh, &c->rfd); + channel_close_fd(ssh, &c->wfd); + channel_close_fd(ssh, &c->efd); +} + +static void +fwd_perm_clear(ForwardPermission *fp) +{ + free(fp->host_to_connect); + free(fp->listen_host); + free(fp->listen_path); + bzero(fp, sizeof(*fp)); +} + +enum { FWDPERM_USER, FWDPERM_ADMIN }; + +static int +fwd_perm_list_add(struct ssh *ssh, int which, + const char *host_to_connect, int port_to_connect, + const char *listen_host, const char *listen_path, int listen_port, + Channel *downstream) +{ + ForwardPermission **fpl; + u_int n, *nfpl; + + switch (which) { + case FWDPERM_USER: + fpl = &ssh->chanctxt->permitted_opens; + nfpl = &ssh->chanctxt->num_permitted_opens; + break; + case FWDPERM_ADMIN: + fpl = &ssh->chanctxt->permitted_adm_opens; + nfpl = &ssh->chanctxt->num_adm_permitted_opens; + break; + default: + fatal("%s: invalid list %d", __func__, which); + } + + if (*nfpl >= INT_MAX) + fatal("%s: overflow", __func__); + + *fpl = xrecallocarray(*fpl, *nfpl, *nfpl + 1, sizeof(**fpl)); + n = (*nfpl)++; +#define MAYBE_DUP(s) ((s == NULL) ? NULL : xstrdup(s)) + (*fpl)[n].host_to_connect = MAYBE_DUP(host_to_connect); + (*fpl)[n].port_to_connect = port_to_connect; + (*fpl)[n].listen_host = MAYBE_DUP(listen_host); + (*fpl)[n].listen_path = MAYBE_DUP(listen_path); + (*fpl)[n].listen_port = listen_port; + (*fpl)[n].downstream = downstream; +#undef MAYBE_DUP + return (int)n; +} + +static void +mux_remove_remote_forwardings(struct ssh *ssh, Channel *c) +{ + struct ssh_channels *sc = ssh->chanctxt; + ForwardPermission *fp; + int r; + u_int i; + + for (i = 0; i < sc->num_permitted_opens; i++) { + fp = &sc->permitted_opens[i]; + if (fp->downstream != c) + continue; + + /* cancel on the server, since mux client is gone */ + debug("channel %d: cleanup remote forward for %s:%u", + c->self, fp->listen_host, fp->listen_port); + if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || + (r = sshpkt_put_cstring(ssh, + "cancel-tcpip-forward")) != 0 || + (r = sshpkt_put_u8(ssh, 0)) != 0 || + (r = sshpkt_put_cstring(ssh, + channel_rfwd_bind_host(fp->listen_host))) != 0 || + (r = sshpkt_put_u32(ssh, fp->listen_port)) != 0 || + (r = sshpkt_send(ssh)) != 0) { + fatal("%s: channel %i: %s", __func__, + c->self, ssh_err(r)); + } + fwd_perm_clear(fp); /* unregister */ + } } /* Free the channel and close its fd/socket. */ void -channel_free(Channel *c) +channel_free(struct ssh *ssh, Channel *c) { + struct ssh_channels *sc = ssh->chanctxt; char *s; u_int i, n; Channel *other; struct channel_confirm *cc; - for (n = 0, i = 0; i < channels_alloc; i++) { - if ((other = channels[i]) != NULL) { - n++; - - /* detach from mux client and prepare for closing */ - if (c->type == SSH_CHANNEL_MUX_CLIENT && - other->type == SSH_CHANNEL_MUX_PROXY && - other->mux_ctx == c) { - other->mux_ctx = NULL; - other->type = SSH_CHANNEL_OPEN; - other->istate = CHAN_INPUT_CLOSED; - other->ostate = CHAN_OUTPUT_CLOSED; - } + for (n = 0, i = 0; i < sc->channels_alloc; i++) { + if ((other = sc->channels[i]) == NULL) + continue; + n++; + /* detach from mux client and prepare for closing */ + if (c->type == SSH_CHANNEL_MUX_CLIENT && + other->type == SSH_CHANNEL_MUX_PROXY && + other->mux_ctx == c) { + other->mux_ctx = NULL; + other->type = SSH_CHANNEL_OPEN; + other->istate = CHAN_INPUT_CLOSED; + other->ostate = CHAN_OUTPUT_CLOSED; } } debug("channel %d: free: %s, nchannels %u", c->self, c->remote_name ? c->remote_name : "???", n); - /* XXX more MUX cleanup: remove remote forwardings */ - if (c->type == SSH_CHANNEL_MUX_CLIENT) { - for (i = 0; i < (u_int)num_permitted_opens; i++) { - if (permitted_opens[i].downstream != c) - continue; - /* cancel on the server, since mux client is gone */ - debug("channel %d: cleanup remote forward for %s:%u", - c->self, - permitted_opens[i].listen_host, - permitted_opens[i].listen_port); - packet_start(SSH2_MSG_GLOBAL_REQUEST); - packet_put_cstring("cancel-tcpip-forward"); - packet_put_char(0); - packet_put_cstring(channel_rfwd_bind_host( - permitted_opens[i].listen_host)); - packet_put_int(permitted_opens[i].listen_port); - packet_send(); - /* unregister */ - permitted_opens[i].listen_port = 0; - permitted_opens[i].port_to_connect = 0; - free(permitted_opens[i].host_to_connect); - permitted_opens[i].host_to_connect = NULL; - free(permitted_opens[i].listen_host); - permitted_opens[i].listen_host = NULL; - permitted_opens[i].listen_path = NULL; - permitted_opens[i].downstream = NULL; - } - } + if (c->type == SSH_CHANNEL_MUX_CLIENT) + mux_remove_remote_forwardings(ssh, c); - s = channel_open_message(); + s = channel_open_message(ssh); debug3("channel %d: status: %s", c->self, s); free(s); - if (c->sock != -1) - shutdown(c->sock, SHUT_RDWR); - channel_close_fds(c); - buffer_free(&c->input); - buffer_free(&c->output); - buffer_free(&c->extended); + channel_close_fds(ssh, c); + sshbuf_free(c->input); + sshbuf_free(c->output); + sshbuf_free(c->extended); + c->input = c->output = c->extended = NULL; free(c->remote_name); c->remote_name = NULL; free(c->path); @@ -496,25 +569,26 @@ channel_free(Channel *c) c->listening_addr = NULL; while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) { if (cc->abandon_cb != NULL) - cc->abandon_cb(c, cc->ctx); + cc->abandon_cb(ssh, c, cc->ctx); TAILQ_REMOVE(&c->status_confirms, cc, entry); explicit_bzero(cc, sizeof(*cc)); free(cc); } if (c->filter_cleanup != NULL && c->filter_ctx != NULL) - c->filter_cleanup(c->self, c->filter_ctx); - channels[c->self] = NULL; + c->filter_cleanup(ssh, c->self, c->filter_ctx); + sc->channels[c->self] = NULL; + explicit_bzero(c, sizeof(*c)); free(c); } void -channel_free_all(void) +channel_free_all(struct ssh *ssh) { u_int i; - for (i = 0; i < channels_alloc; i++) - if (channels[i] != NULL) - channel_free(channels[i]); + for (i = 0; i < ssh->chanctxt->channels_alloc; i++) + if (ssh->chanctxt->channels[i] != NULL) + channel_free(ssh, ssh->chanctxt->channels[i]); } /* @@ -522,26 +596,26 @@ channel_free_all(void) * descriptors after a fork. */ void -channel_close_all(void) +channel_close_all(struct ssh *ssh) { u_int i; - for (i = 0; i < channels_alloc; i++) - if (channels[i] != NULL) - channel_close_fds(channels[i]); + for (i = 0; i < ssh->chanctxt->channels_alloc; i++) + if (ssh->chanctxt->channels[i] != NULL) + channel_close_fds(ssh, ssh->chanctxt->channels[i]); } /* * Stop listening to channels. */ void -channel_stop_listening(void) +channel_stop_listening(struct ssh *ssh) { u_int i; Channel *c; - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; + for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { + c = ssh->chanctxt->channels[i]; if (c != NULL) { switch (c->type) { case SSH_CHANNEL_AUTH_SOCKET: @@ -550,8 +624,8 @@ channel_stop_listening(void) case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_UNIX_LISTENER: case SSH_CHANNEL_RUNIX_LISTENER: - channel_close_fd(&c->sock); - channel_free(c); + channel_close_fd(ssh, &c->sock); + channel_free(ssh, c); break; } } @@ -563,28 +637,20 @@ channel_stop_listening(void) * more channel is overfull. */ int -channel_not_very_much_buffered_data(void) +channel_not_very_much_buffered_data(struct ssh *ssh) { u_int i; + u_int maxsize = ssh_packet_get_maxsize(ssh); Channel *c; - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; - if (c != NULL && c->type == SSH_CHANNEL_OPEN) { -#if 0 - if (!compat20 && - buffer_len(&c->input) > packet_get_maxsize()) { - debug2("channel %d: big input buffer %d", - c->self, buffer_len(&c->input)); - return 0; - } -#endif - if (buffer_len(&c->output) > packet_get_maxsize()) { - debug2("channel %d: big output buffer %u > %u", - c->self, buffer_len(&c->output), - packet_get_maxsize()); - return 0; - } + for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { + c = ssh->chanctxt->channels[i]; + if (c == NULL || c->type != SSH_CHANNEL_OPEN) + continue; + if (sshbuf_len(c->output) > maxsize) { + debug2("channel %d: big output buffer %zu > %u", + c->self, sshbuf_len(c->output), maxsize); + return 0; } } return 1; @@ -592,13 +658,13 @@ channel_not_very_much_buffered_data(void) /* Returns true if any channel is still open. */ int -channel_still_open(void) +channel_still_open(struct ssh *ssh) { u_int i; Channel *c; - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; + for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { + c = ssh->chanctxt->channels[i]; if (c == NULL) continue; switch (c->type) { @@ -609,6 +675,7 @@ channel_still_open(void) case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_AUTH_SOCKET: case SSH_CHANNEL_DYNAMIC: + case SSH_CHANNEL_RDYNAMIC_OPEN: case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_ZOMBIE: case SSH_CHANNEL_ABANDONED: @@ -616,22 +683,16 @@ channel_still_open(void) case SSH_CHANNEL_RUNIX_LISTENER: continue; case SSH_CHANNEL_LARVAL: - if (!compat20) - fatal("cannot happen: SSH_CHANNEL_LARVAL"); continue; case SSH_CHANNEL_OPENING: case SSH_CHANNEL_OPEN: + case SSH_CHANNEL_RDYNAMIC_FINISH: case SSH_CHANNEL_X11_OPEN: case SSH_CHANNEL_MUX_CLIENT: case SSH_CHANNEL_MUX_PROXY: return 1; - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: - if (!compat13) - fatal("cannot happen: OUT_DRAIN"); - return 1; default: - fatal("channel_still_open: bad channel type %d", c->type); + fatal("%s: bad channel type %d", __func__, c->type); /* NOTREACHED */ } } @@ -640,18 +701,20 @@ channel_still_open(void) /* Returns the id of an open channel suitable for keepaliving */ int -channel_find_open(void) +channel_find_open(struct ssh *ssh) { u_int i; Channel *c; - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; - if (c == NULL || c->remote_id < 0) + for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { + c = ssh->chanctxt->channels[i]; + if (c == NULL || !c->have_remote_id) continue; switch (c->type) { case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_DYNAMIC: + case SSH_CHANNEL_RDYNAMIC_OPEN: + case SSH_CHANNEL_RDYNAMIC_FINISH: case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER: @@ -670,13 +733,8 @@ channel_find_open(void) case SSH_CHANNEL_OPEN: case SSH_CHANNEL_X11_OPEN: return i; - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: - if (!compat13) - fatal("cannot happen: OUT_DRAIN"); - return i; default: - fatal("channel_find_open: bad channel type %d", c->type); + fatal("%s: bad channel type %d", __func__, c->type); /* NOTREACHED */ } } @@ -689,18 +747,21 @@ channel_find_open(void) * newlines. */ char * -channel_open_message(void) +channel_open_message(struct ssh *ssh) { - Buffer buffer; + struct sshbuf *buf; Channel *c; - char buf[1024], *cp; u_int i; + int r; + char *ret; - buffer_init(&buffer); - snprintf(buf, sizeof buf, "The following connections are open:\r\n"); - buffer_append(&buffer, buf, strlen(buf)); - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; + if ((buf = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new", __func__); + if ((r = sshbuf_putf(buf, + "The following connections are open:\r\n")) != 0) + fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r)); + for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { + c = ssh->chanctxt->channels[i]; if (c == NULL) continue; switch (c->type) { @@ -719,75 +780,95 @@ channel_open_message(void) case SSH_CHANNEL_OPENING: case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_DYNAMIC: + case SSH_CHANNEL_RDYNAMIC_OPEN: + case SSH_CHANNEL_RDYNAMIC_FINISH: case SSH_CHANNEL_OPEN: case SSH_CHANNEL_X11_OPEN: - case SSH_CHANNEL_INPUT_DRAINING: - case SSH_CHANNEL_OUTPUT_DRAINING: case SSH_CHANNEL_MUX_PROXY: case SSH_CHANNEL_MUX_CLIENT: - snprintf(buf, sizeof buf, - " #%d %.300s (t%d r%d i%u/%d o%u/%d fd %d/%d cc %d)\r\n", + if ((r = sshbuf_putf(buf, " #%d %.300s " + "(t%d %s%u i%u/%zu o%u/%zu fd %d/%d cc %d)\r\n", c->self, c->remote_name, - c->type, c->remote_id, - c->istate, buffer_len(&c->input), - c->ostate, buffer_len(&c->output), - c->rfd, c->wfd, c->ctl_chan); - buffer_append(&buffer, buf, strlen(buf)); + c->type, + c->have_remote_id ? "r" : "nr", c->remote_id, + c->istate, sshbuf_len(c->input), + c->ostate, sshbuf_len(c->output), + c->rfd, c->wfd, c->ctl_chan)) != 0) + fatal("%s: sshbuf_putf: %s", + __func__, ssh_err(r)); continue; default: - fatal("channel_open_message: bad channel type %d", c->type); + fatal("%s: bad channel type %d", __func__, c->type); /* NOTREACHED */ } } - buffer_append(&buffer, "\0", 1); - cp = xstrdup((char *)buffer_ptr(&buffer)); - buffer_free(&buffer); - return cp; + if ((ret = sshbuf_dup_string(buf)) == NULL) + fatal("%s: sshbuf_dup_string", __func__); + sshbuf_free(buf); + return ret; +} + +static void +open_preamble(struct ssh *ssh, const char *where, Channel *c, const char *type) +{ + int r; + + if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 || + (r = sshpkt_put_cstring(ssh, type)) != 0 || + (r = sshpkt_put_u32(ssh, c->self)) != 0 || + (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || + (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) { + fatal("%s: channel %i: open: %s", where, c->self, ssh_err(r)); + } } void -channel_send_open(int id) +channel_send_open(struct ssh *ssh, int id) { - Channel *c = channel_lookup(id); + Channel *c = channel_lookup(ssh, id); + int r; if (c == NULL) { logit("channel_send_open: %d: bad id", id); return; } debug2("channel %d: send open", id); - packet_start(SSH2_MSG_CHANNEL_OPEN); - packet_put_cstring(c->ctype); - packet_put_int(c->self); - packet_put_int(c->local_window); - packet_put_int(c->local_maxpacket); - packet_send(); + open_preamble(ssh, __func__, c, c->ctype); + if ((r = sshpkt_send(ssh)) != 0) + fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); } void -channel_request_start(int id, char *service, int wantconfirm) +channel_request_start(struct ssh *ssh, int id, char *service, int wantconfirm) { - Channel *c = channel_lookup(id); + Channel *c = channel_lookup(ssh, id); + int r; if (c == NULL) { - logit("channel_request_start: %d: unknown channel id", id); + logit("%s: %d: unknown channel id", __func__, id); return; } + if (!c->have_remote_id) + fatal(":%s: channel %d: no remote id", __func__, c->self); + debug2("channel %d: request %s confirm %d", id, service, wantconfirm); - packet_start(SSH2_MSG_CHANNEL_REQUEST); - packet_put_int(c->remote_id); - packet_put_cstring(service); - packet_put_char(wantconfirm); + if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || + (r = sshpkt_put_cstring(ssh, service)) != 0 || + (r = sshpkt_put_u8(ssh, wantconfirm)) != 0) { + fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); + } } void -channel_register_status_confirm(int id, channel_confirm_cb *cb, - channel_confirm_abandon_cb *abandon_cb, void *ctx) +channel_register_status_confirm(struct ssh *ssh, int id, + channel_confirm_cb *cb, channel_confirm_abandon_cb *abandon_cb, void *ctx) { struct channel_confirm *cc; Channel *c; - if ((c = channel_lookup(id)) == NULL) - fatal("channel_register_expect: %d: bad id", id); + if ((c = channel_lookup(ssh, id)) == NULL) + fatal("%s: %d: bad id", __func__, id); cc = xcalloc(1, sizeof(*cc)); cc->cb = cb; @@ -797,12 +878,13 @@ channel_register_status_confirm(int id, channel_confirm_cb *cb, } void -channel_register_open_confirm(int id, channel_open_fn *fn, void *ctx) +channel_register_open_confirm(struct ssh *ssh, int id, + channel_open_fn *fn, void *ctx) { - Channel *c = channel_lookup(id); + Channel *c = channel_lookup(ssh, id); if (c == NULL) { - logit("channel_register_open_confirm: %d: bad id", id); + logit("%s: %d: bad id", __func__, id); return; } c->open_confirm = fn; @@ -810,12 +892,13 @@ channel_register_open_confirm(int id, channel_open_fn *fn, void *ctx) } void -channel_register_cleanup(int id, channel_callback_fn *fn, int do_close) +channel_register_cleanup(struct ssh *ssh, int id, + channel_callback_fn *fn, int do_close) { - Channel *c = channel_by_id(id); + Channel *c = channel_by_id(ssh, id); if (c == NULL) { - logit("channel_register_cleanup: %d: bad id", id); + logit("%s: %d: bad id", __func__, id); return; } c->detach_user = fn; @@ -823,12 +906,12 @@ channel_register_cleanup(int id, channel_callback_fn *fn, int do_close) } void -channel_cancel_cleanup(int id) +channel_cancel_cleanup(struct ssh *ssh, int id) { - Channel *c = channel_by_id(id); + Channel *c = channel_by_id(ssh, id); if (c == NULL) { - logit("channel_cancel_cleanup: %d: bad id", id); + logit("%s: %d: bad id", __func__, id); return; } c->detach_user = NULL; @@ -836,13 +919,13 @@ channel_cancel_cleanup(int id) } void -channel_register_filter(int id, channel_infilter_fn *ifn, +channel_register_filter(struct ssh *ssh, int id, channel_infilter_fn *ifn, channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx) { - Channel *c = channel_lookup(id); + Channel *c = channel_lookup(ssh, id); if (c == NULL) { - logit("channel_register_filter: %d: bad id", id); + logit("%s: %d: bad id", __func__, id); return; } c->input_filter = ifn; @@ -852,118 +935,80 @@ channel_register_filter(int id, channel_infilter_fn *ifn, } void -channel_set_fds(int id, int rfd, int wfd, int efd, +channel_set_fds(struct ssh *ssh, int id, int rfd, int wfd, int efd, int extusage, int nonblock, int is_tty, u_int window_max) { - Channel *c = channel_lookup(id); + Channel *c = channel_lookup(ssh, id); + int r; if (c == NULL || c->type != SSH_CHANNEL_LARVAL) fatal("channel_activate for non-larval channel %d.", id); - channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, is_tty); + if (!c->have_remote_id) + fatal(":%s: channel %d: no remote id", __func__, c->self); + + channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty); c->type = SSH_CHANNEL_OPEN; c->local_window = c->local_window_max = window_max; - packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); - packet_put_int(c->remote_id); - packet_put_int(c->local_window); - packet_send(); + + if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || + (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); } -/* - * 'channel_pre*' are called just before select() to add any bits relevant to - * channels in the select bitmasks. - */ -/* - * 'channel_post*': perform any appropriate operations for channels which - * have events pending. - */ -typedef void chan_fn(Channel *c, fd_set *readset, fd_set *writeset); -chan_fn *channel_pre[SSH_CHANNEL_MAX_TYPE]; -chan_fn *channel_post[SSH_CHANNEL_MAX_TYPE]; - -/* ARGSUSED */ static void -channel_pre_listener(Channel *c, fd_set *readset, fd_set *writeset) +channel_pre_listener(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { FD_SET(c->sock, readset); } -/* ARGSUSED */ static void -channel_pre_connecting(Channel *c, fd_set *readset, fd_set *writeset) +channel_pre_connecting(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { debug3("channel %d: waiting for connection", c->self); FD_SET(c->sock, writeset); } static void -channel_pre_open_13(Channel *c, fd_set *readset, fd_set *writeset) +channel_pre_open(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { - if (buffer_len(&c->input) < packet_get_maxsize()) - FD_SET(c->sock, readset); - if (buffer_len(&c->output) > 0) - FD_SET(c->sock, writeset); -} - -static void -channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset) -{ - u_int limit = compat20 ? c->remote_window : packet_get_maxsize(); - if (c->istate == CHAN_INPUT_OPEN && - limit > 0 && - buffer_len(&c->input) < limit && - buffer_check_alloc(&c->input, CHAN_RBUF)) + c->remote_window > 0 && + sshbuf_len(c->input) < c->remote_window && + sshbuf_check_reserve(c->input, CHAN_RBUF) == 0) FD_SET(c->rfd, readset); if (c->ostate == CHAN_OUTPUT_OPEN || c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { - if (buffer_len(&c->output) > 0) { + if (sshbuf_len(c->output) > 0) { FD_SET(c->wfd, writeset); } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { if (CHANNEL_EFD_OUTPUT_ACTIVE(c)) - debug2("channel %d: obuf_empty delayed efd %d/(%d)", - c->self, c->efd, buffer_len(&c->extended)); + debug2("channel %d: " + "obuf_empty delayed efd %d/(%zu)", c->self, + c->efd, sshbuf_len(c->extended)); else - chan_obuf_empty(c); + chan_obuf_empty(ssh, c); } } /** XXX check close conditions, too */ - if (compat20 && c->efd != -1 && - !(c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED)) { + if (c->efd != -1 && !(c->istate == CHAN_INPUT_CLOSED && + c->ostate == CHAN_OUTPUT_CLOSED)) { if (c->extended_usage == CHAN_EXTENDED_WRITE && - buffer_len(&c->extended) > 0) + sshbuf_len(c->extended) > 0) FD_SET(c->efd, writeset); else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) && (c->extended_usage == CHAN_EXTENDED_READ || c->extended_usage == CHAN_EXTENDED_IGNORE) && - buffer_len(&c->extended) < c->remote_window) + sshbuf_len(c->extended) < c->remote_window) FD_SET(c->efd, readset); } /* XXX: What about efd? races? */ } -/* ARGSUSED */ -static void -channel_pre_input_draining(Channel *c, fd_set *readset, fd_set *writeset) -{ - if (buffer_len(&c->input) == 0) { - packet_start(SSH_MSG_CHANNEL_CLOSE); - packet_put_int(c->remote_id); - packet_send(); - c->type = SSH_CHANNEL_CLOSED; - debug2("channel %d: closing after input drain.", c->self); - } -} - -/* ARGSUSED */ -static void -channel_pre_output_draining(Channel *c, fd_set *readset, fd_set *writeset) -{ - if (buffer_len(&c->output) == 0) - chan_mark_dead(c); - else - FD_SET(c->sock, writeset); -} - /* * This is a special state for X11 authentication spoofing. An opened X11 * connection (when authentication spoofing is being done) remains in this @@ -974,24 +1019,26 @@ channel_pre_output_draining(Channel *c, fd_set *readset, fd_set *writeset) * Returns: 0 = need more data, -1 = wrong cookie, 1 = ok */ static int -x11_open_helper(Buffer *b) +x11_open_helper(struct ssh *ssh, struct sshbuf *b) { + struct ssh_channels *sc = ssh->chanctxt; u_char *ucp; u_int proto_len, data_len; /* Is this being called after the refusal deadline? */ - if (x11_refuse_time != 0 && (u_int)monotime() >= x11_refuse_time) { + if (sc->x11_refuse_time != 0 && + (u_int)monotime() >= sc->x11_refuse_time) { verbose("Rejected X11 connection after ForwardX11Timeout " "expired"); return -1; } /* Check if the fixed size part of the packet is in buffer. */ - if (buffer_len(b) < 12) + if (sshbuf_len(b) < 12) return 0; /* Parse the lengths of variable-length fields. */ - ucp = buffer_ptr(b); + ucp = sshbuf_mutable_ptr(b); if (ucp[0] == 0x42) { /* Byte order MSB first. */ proto_len = 256 * ucp[6] + ucp[7]; data_len = 256 * ucp[8] + ucp[9]; @@ -1005,27 +1052,27 @@ x11_open_helper(Buffer *b) } /* Check if the whole packet is in buffer. */ - if (buffer_len(b) < + if (sshbuf_len(b) < 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3)) return 0; /* Check if authentication protocol matches. */ - if (proto_len != strlen(x11_saved_proto) || - memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) { + if (proto_len != strlen(sc->x11_saved_proto) || + memcmp(ucp + 12, sc->x11_saved_proto, proto_len) != 0) { debug2("X11 connection uses different authentication protocol."); return -1; } /* Check if authentication data matches our fake data. */ - if (data_len != x11_fake_data_len || + if (data_len != sc->x11_fake_data_len || timingsafe_bcmp(ucp + 12 + ((proto_len + 3) & ~3), - x11_fake_data, x11_fake_data_len) != 0) { + sc->x11_fake_data, sc->x11_fake_data_len) != 0) { debug2("X11 auth data does not match fake data."); return -1; } /* Check fake data length */ - if (x11_fake_data_len != x11_saved_data_len) { + if (sc->x11_fake_data_len != sc->x11_saved_data_len) { error("X11 fake_data_len %d != saved_data_len %d", - x11_fake_data_len, x11_saved_data_len); + sc->x11_fake_data_len, sc->x11_saved_data_len); return -1; } /* @@ -1034,90 +1081,63 @@ x11_open_helper(Buffer *b) * data. */ memcpy(ucp + 12 + ((proto_len + 3) & ~3), - x11_saved_data, x11_saved_data_len); + sc->x11_saved_data, sc->x11_saved_data_len); return 1; } static void -channel_pre_x11_open_13(Channel *c, fd_set *readset, fd_set *writeset) +channel_pre_x11_open(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { - int ret = x11_open_helper(&c->output); - - if (ret == 1) { - /* Start normal processing for the channel. */ - c->type = SSH_CHANNEL_OPEN; - channel_pre_open_13(c, readset, writeset); - } else if (ret == -1) { - /* - * We have received an X11 connection that has bad - * authentication information. - */ - logit("X11 connection rejected because of wrong authentication."); - buffer_clear(&c->input); - buffer_clear(&c->output); - channel_close_fd(&c->sock); - c->sock = -1; - c->type = SSH_CHANNEL_CLOSED; - packet_start(SSH_MSG_CHANNEL_CLOSE); - packet_put_int(c->remote_id); - packet_send(); - } -} - -static void -channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset) -{ - int ret = x11_open_helper(&c->output); + int ret = x11_open_helper(ssh, c->output); /* c->force_drain = 1; */ if (ret == 1) { c->type = SSH_CHANNEL_OPEN; - channel_pre_open(c, readset, writeset); + channel_pre_open(ssh, c, readset, writeset); } else if (ret == -1) { logit("X11 connection rejected because of wrong authentication."); - debug2("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate); - chan_read_failed(c); - buffer_clear(&c->input); - chan_ibuf_empty(c); - buffer_clear(&c->output); - /* for proto v1, the peer will send an IEOF */ - if (compat20) - chan_write_failed(c); - else - c->type = SSH_CHANNEL_OPEN; + debug2("X11 rejected %d i%d/o%d", + c->self, c->istate, c->ostate); + chan_read_failed(ssh, c); + sshbuf_reset(c->input); + chan_ibuf_empty(ssh, c); + sshbuf_reset(c->output); + chan_write_failed(ssh, c); debug2("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate); } } static void -channel_pre_mux_client(Channel *c, fd_set *readset, fd_set *writeset) +channel_pre_mux_client(struct ssh *ssh, + Channel *c, fd_set *readset, fd_set *writeset) { if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause && - buffer_check_alloc(&c->input, CHAN_RBUF)) + sshbuf_check_reserve(c->input, CHAN_RBUF) == 0) FD_SET(c->rfd, readset); if (c->istate == CHAN_INPUT_WAIT_DRAIN) { /* clear buffer immediately (discard any partial packet) */ - buffer_clear(&c->input); - chan_ibuf_empty(c); + sshbuf_reset(c->input); + chan_ibuf_empty(ssh, c); /* Start output drain. XXX just kill chan? */ - chan_rcvd_oclose(c); + chan_rcvd_oclose(ssh, c); } if (c->ostate == CHAN_OUTPUT_OPEN || c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { - if (buffer_len(&c->output) > 0) + if (sshbuf_len(c->output) > 0) FD_SET(c->wfd, writeset); else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) - chan_obuf_empty(c); + chan_obuf_empty(ssh, c); } } /* try to decode a socks4 header */ -/* ARGSUSED */ static int -channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) +channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output) { - char *p, *host; + const u_char *p; + char *host; u_int len, have, i, found, need; char username[256]; struct { @@ -1126,14 +1146,15 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) u_int16_t dest_port; struct in_addr dest_addr; } s4_req, s4_rsp; + int r; debug2("channel %d: decode socks4", c->self); - have = buffer_len(&c->input); + have = sshbuf_len(input); len = sizeof(s4_req); if (have < len) return 0; - p = (char *)buffer_ptr(&c->input); + p = sshbuf_ptr(input); need = 1; /* SOCKS4A uses an invalid IP address 0.0.0.x */ @@ -1158,46 +1179,55 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) } if (found < need) return 0; - buffer_get(&c->input, (char *)&s4_req.version, 1); - buffer_get(&c->input, (char *)&s4_req.command, 1); - buffer_get(&c->input, (char *)&s4_req.dest_port, 2); - buffer_get(&c->input, (char *)&s4_req.dest_addr, 4); - have = buffer_len(&c->input); - p = (char *)buffer_ptr(&c->input); - if (memchr(p, '\0', have) == NULL) - fatal("channel %d: decode socks4: user not nul terminated", + if ((r = sshbuf_get(input, &s4_req.version, 1)) != 0 || + (r = sshbuf_get(input, &s4_req.command, 1)) != 0 || + (r = sshbuf_get(input, &s4_req.dest_port, 2)) != 0 || + (r = sshbuf_get(input, &s4_req.dest_addr, 4)) != 0) { + debug("channels %d: decode socks4: %s", c->self, ssh_err(r)); + return -1; + } + have = sshbuf_len(input); + p = sshbuf_ptr(input); + if (memchr(p, '\0', have) == NULL) { + error("channel %d: decode socks4: user not nul terminated", c->self); + return -1; + } len = strlen(p); debug2("channel %d: decode socks4: user %s/%d", c->self, p, len); - len++; /* trailing '\0' */ - if (len > have) - fatal("channel %d: decode socks4: len %d > have %d", - c->self, len, have); + len++; /* trailing '\0' */ strlcpy(username, p, sizeof(username)); - buffer_consume(&c->input, len); - + if ((r = sshbuf_consume(input, len)) != 0) { + fatal("%s: channel %d: consume: %s", __func__, + c->self, ssh_err(r)); + } free(c->path); c->path = NULL; if (need == 1) { /* SOCKS4: one string */ host = inet_ntoa(s4_req.dest_addr); c->path = xstrdup(host); } else { /* SOCKS4A: two strings */ - have = buffer_len(&c->input); - p = (char *)buffer_ptr(&c->input); + have = sshbuf_len(input); + p = sshbuf_ptr(input); + if (memchr(p, '\0', have) == NULL) { + error("channel %d: decode socks4a: host not nul " + "terminated", c->self); + return -1; + } len = strlen(p); debug2("channel %d: decode socks4a: host %s/%d", c->self, p, len); len++; /* trailing '\0' */ - if (len > have) - fatal("channel %d: decode socks4a: len %d > have %d", - c->self, len, have); if (len > NI_MAXHOST) { error("channel %d: hostname \"%.100s\" too long", c->self, p); return -1; } c->path = xstrdup(p); - buffer_consume(&c->input, len); + if ((r = sshbuf_consume(input, len)) != 0) { + fatal("%s: channel %d: consume: %s", __func__, + c->self, ssh_err(r)); + } } c->host_port = ntohs(s4_req.dest_port); @@ -1213,7 +1243,10 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) s4_rsp.command = 90; /* cd: req granted */ s4_rsp.dest_port = 0; /* ignored */ s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */ - buffer_append(&c->output, &s4_rsp, sizeof(s4_rsp)); + if ((r = sshbuf_put(output, &s4_rsp, sizeof(s4_rsp))) != 0) { + fatal("%s: channel %d: append reply: %s", __func__, + c->self, ssh_err(r)); + } return 1; } @@ -1226,10 +1259,10 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) #define SSH_SOCKS5_CONNECT 0x01 #define SSH_SOCKS5_SUCCESS 0x00 -/* ARGSUSED */ static int -channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) +channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output) { + /* XXX use get/put_u8 instead of trusting struct padding */ struct { u_int8_t version; u_int8_t command; @@ -1238,14 +1271,15 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) } s5_req, s5_rsp; u_int16_t dest_port; char dest_addr[255+1], ntop[INET6_ADDRSTRLEN]; - u_char *p; + const u_char *p; u_int have, need, i, found, nmethods, addrlen, af; + int r; debug2("channel %d: decode socks5", c->self); - p = buffer_ptr(&c->input); + p = sshbuf_ptr(input); if (p[0] != 0x05) return -1; - have = buffer_len(&c->input); + have = sshbuf_len(input); if (!(c->flags & SSH_SOCKS5_AUTHDONE)) { /* format: ver | nmethods | methods */ if (have < 2) @@ -1265,10 +1299,16 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) c->self); return -1; } - buffer_consume(&c->input, nmethods + 2); - buffer_put_char(&c->output, 0x05); /* version */ - buffer_put_char(&c->output, SSH_SOCKS5_NOAUTH); /* method */ - FD_SET(c->sock, writeset); + if ((r = sshbuf_consume(input, nmethods + 2)) != 0) { + fatal("%s: channel %d: consume: %s", __func__, + c->self, ssh_err(r)); + } + /* version, method */ + if ((r = sshbuf_put_u8(output, 0x05)) != 0 || + (r = sshbuf_put_u8(output, SSH_SOCKS5_NOAUTH)) != 0) { + fatal("%s: channel %d: append reply: %s", __func__, + c->self, ssh_err(r)); + } c->flags |= SSH_SOCKS5_AUTHDONE; debug2("channel %d: socks5 auth done", c->self); return 0; /* need more */ @@ -1305,11 +1345,22 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) need++; if (have < need) return 0; - buffer_consume(&c->input, sizeof(s5_req)); - if (s5_req.atyp == SSH_SOCKS5_DOMAIN) - buffer_consume(&c->input, 1); /* host string length */ - buffer_get(&c->input, &dest_addr, addrlen); - buffer_get(&c->input, (char *)&dest_port, 2); + if ((r = sshbuf_consume(input, sizeof(s5_req))) != 0) { + fatal("%s: channel %d: consume: %s", __func__, + c->self, ssh_err(r)); + } + if (s5_req.atyp == SSH_SOCKS5_DOMAIN) { + /* host string length */ + if ((r = sshbuf_consume(input, 1)) != 0) { + fatal("%s: channel %d: consume: %s", __func__, + c->self, ssh_err(r)); + } + } + if ((r = sshbuf_get(input, &dest_addr, addrlen)) != 0 || + (r = sshbuf_get(input, &dest_port, 2)) != 0) { + debug("channel %d: parse addr/port: %s", c->self, ssh_err(r)); + return -1; + } dest_addr[addrlen] = '\0'; free(c->path); c->path = NULL; @@ -1336,22 +1387,23 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) s5_rsp.atyp = SSH_SOCKS5_IPV4; dest_port = 0; /* ignored */ - buffer_append(&c->output, &s5_rsp, sizeof(s5_rsp)); - buffer_put_int(&c->output, ntohl(INADDR_ANY)); /* bind address */ - buffer_append(&c->output, &dest_port, sizeof(dest_port)); + if ((r = sshbuf_put(output, &s5_rsp, sizeof(s5_rsp))) != 0 || + (r = sshbuf_put_u32(output, ntohl(INADDR_ANY))) != 0 || + (r = sshbuf_put(output, &dest_port, sizeof(dest_port))) != 0) + fatal("%s: channel %d: append reply: %s", __func__, + c->self, ssh_err(r)); return 1; } Channel * -channel_connect_stdio_fwd(const char *host_to_connect, u_short port_to_connect, - int in, int out) +channel_connect_stdio_fwd(struct ssh *ssh, + const char *host_to_connect, u_short port_to_connect, int in, int out) { Channel *c; - debug("channel_connect_stdio_fwd %s:%d", host_to_connect, - port_to_connect); + debug("%s %s:%d", __func__, host_to_connect, port_to_connect); - c = channel_new("stdio-forward", SSH_CHANNEL_OPENING, in, out, + c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING, in, out, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "stdio-forward", /*nonblock*/0); @@ -1360,23 +1412,24 @@ channel_connect_stdio_fwd(const char *host_to_connect, u_short port_to_connect, c->listening_port = 0; c->force_drain = 1; - channel_register_fds(c, in, out, -1, 0, 1, 0); - port_open_helper(c, "direct-tcpip"); + channel_register_fds(ssh, c, in, out, -1, 0, 1, 0); + port_open_helper(ssh, c, "direct-tcpip"); return c; } /* dynamic port forwarding */ static void -channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset) +channel_pre_dynamic(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { - u_char *p; + const u_char *p; u_int have; int ret; - have = buffer_len(&c->input); + have = sshbuf_len(c->input); debug2("channel %d: pre_dynamic: have %d", c->self, have); - /* buffer_dump(&c->input); */ + /* sshbuf_dump(c->input, stderr); */ /* check if the fixed size part of the packet is in buffer. */ if (have < 3) { /* need more */ @@ -1384,105 +1437,174 @@ channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset) return; } /* try to guess the protocol */ - p = buffer_ptr(&c->input); + p = sshbuf_ptr(c->input); + /* XXX sshbuf_peek_u8? */ switch (p[0]) { case 0x04: - ret = channel_decode_socks4(c, readset, writeset); + ret = channel_decode_socks4(c, c->input, c->output); break; case 0x05: - ret = channel_decode_socks5(c, readset, writeset); + ret = channel_decode_socks5(c, c->input, c->output); break; default: ret = -1; break; } if (ret < 0) { - chan_mark_dead(c); + chan_mark_dead(ssh, c); } else if (ret == 0) { debug2("channel %d: pre_dynamic: need more", c->self); /* need more */ FD_SET(c->sock, readset); + if (sshbuf_len(c->output)) + FD_SET(c->sock, writeset); } else { /* switch to the next state */ c->type = SSH_CHANNEL_OPENING; - port_open_helper(c, "direct-tcpip"); + port_open_helper(ssh, c, "direct-tcpip"); + } +} + +/* simulate read-error */ +static void +rdynamic_close(struct ssh *ssh, Channel *c) +{ + c->type = SSH_CHANNEL_OPEN; + chan_read_failed(ssh, c); + sshbuf_reset(c->input); + chan_ibuf_empty(ssh, c); + sshbuf_reset(c->output); + chan_write_failed(ssh, c); +} + +/* reverse dynamic port forwarding */ +static void +channel_before_prepare_select_rdynamic(struct ssh *ssh, Channel *c) +{ + const u_char *p; + u_int have, len; + int r, ret; + + have = sshbuf_len(c->output); + debug2("channel %d: pre_rdynamic: have %d", c->self, have); + /* sshbuf_dump(c->output, stderr); */ + /* EOF received */ + if (c->flags & CHAN_EOF_RCVD) { + if ((r = sshbuf_consume(c->output, have)) != 0) { + fatal("%s: channel %d: consume: %s", + __func__, c->self, ssh_err(r)); + } + rdynamic_close(ssh, c); + return; + } + /* check if the fixed size part of the packet is in buffer. */ + if (have < 3) + return; + /* try to guess the protocol */ + p = sshbuf_ptr(c->output); + switch (p[0]) { + case 0x04: + /* switch input/output for reverse forwarding */ + ret = channel_decode_socks4(c, c->output, c->input); + break; + case 0x05: + ret = channel_decode_socks5(c, c->output, c->input); + break; + default: + ret = -1; + break; + } + if (ret < 0) { + rdynamic_close(ssh, c); + } else if (ret == 0) { + debug2("channel %d: pre_rdynamic: need more", c->self); + /* send socks request to peer */ + len = sshbuf_len(c->input); + if (len > 0 && len < c->remote_window) { + if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || + (r = sshpkt_put_stringb(ssh, c->input)) != 0 || + (r = sshpkt_send(ssh)) != 0) { + fatal("%s: channel %i: rdynamic: %s", __func__, + c->self, ssh_err(r)); + } + if ((r = sshbuf_consume(c->input, len)) != 0) { + fatal("%s: channel %d: consume: %s", + __func__, c->self, ssh_err(r)); + } + c->remote_window -= len; + } + } else if (rdynamic_connect_finish(ssh, c) < 0) { + /* the connect failed */ + rdynamic_close(ssh, c); } } /* This is our fake X11 server socket. */ -/* ARGSUSED */ static void -channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset) +channel_post_x11_listener(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { Channel *nc; struct sockaddr_storage addr; - int newsock, oerrno; + int r, newsock, oerrno, remote_port; socklen_t addrlen; char buf[16384], *remote_ipaddr; - int remote_port; - if (FD_ISSET(c->sock, readset)) { - debug("X11 connection requested."); - addrlen = sizeof(addr); - newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); - if (c->single_connection) { - oerrno = errno; - debug2("single_connection: closing X11 listener."); - channel_close_fd(&c->sock); - chan_mark_dead(c); - errno = oerrno; - } - if (newsock < 0) { - if (errno != EINTR && errno != EWOULDBLOCK && - errno != ECONNABORTED) - error("accept: %.100s", strerror(errno)); - if (errno == EMFILE || errno == ENFILE) - c->notbefore = monotime() + 1; - return; - } - set_nodelay(newsock); - remote_ipaddr = get_peer_ipaddr(newsock); - remote_port = get_peer_port(newsock); - snprintf(buf, sizeof buf, "X11 connection from %.200s port %d", - remote_ipaddr, remote_port); + if (!FD_ISSET(c->sock, readset)) + return; - nc = channel_new("accepted x11 socket", - SSH_CHANNEL_OPENING, newsock, newsock, -1, - c->local_window_max, c->local_maxpacket, 0, buf, 1); - if (compat20) { - packet_start(SSH2_MSG_CHANNEL_OPEN); - packet_put_cstring("x11"); - packet_put_int(nc->self); - packet_put_int(nc->local_window_max); - packet_put_int(nc->local_maxpacket); - /* originator ipaddr and port */ - packet_put_cstring(remote_ipaddr); - if (datafellows & SSH_BUG_X11FWD) { - debug2("ssh2 x11 bug compat mode"); - } else { - packet_put_int(remote_port); - } - packet_send(); - } else { - packet_start(SSH_SMSG_X11_OPEN); - packet_put_int(nc->self); - if (packet_get_protocol_flags() & - SSH_PROTOFLAG_HOST_IN_FWD_OPEN) - packet_put_cstring(buf); - packet_send(); - } - free(remote_ipaddr); + debug("X11 connection requested."); + addrlen = sizeof(addr); + newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); + if (c->single_connection) { + oerrno = errno; + debug2("single_connection: closing X11 listener."); + channel_close_fd(ssh, &c->sock); + chan_mark_dead(ssh, c); + errno = oerrno; } + if (newsock < 0) { + if (errno != EINTR && errno != EWOULDBLOCK && + errno != ECONNABORTED) + error("accept: %.100s", strerror(errno)); + if (errno == EMFILE || errno == ENFILE) + c->notbefore = monotime() + 1; + return; + } + set_nodelay(newsock); + remote_ipaddr = get_peer_ipaddr(newsock); + remote_port = get_peer_port(newsock); + snprintf(buf, sizeof buf, "X11 connection from %.200s port %d", + remote_ipaddr, remote_port); + + nc = channel_new(ssh, "accepted x11 socket", + SSH_CHANNEL_OPENING, newsock, newsock, -1, + c->local_window_max, c->local_maxpacket, 0, buf, 1); + open_preamble(ssh, __func__, nc, "x11"); + if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0) { + fatal("%s: channel %i: reply %s", __func__, + c->self, ssh_err(r)); + } + if ((datafellows & SSH_BUG_X11FWD) != 0) + debug2("channel %d: ssh2 x11 bug compat mode", nc->self); + else if ((r = sshpkt_put_u32(ssh, remote_port)) != 0) { + fatal("%s: channel %i: reply %s", __func__, + c->self, ssh_err(r)); + } + if ((r = sshpkt_send(ssh)) != 0) + fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r)); + free(remote_ipaddr); } static void -port_open_helper(Channel *c, char *rtype) +port_open_helper(struct ssh *ssh, Channel *c, char *rtype) { - char buf[1024]; char *local_ipaddr = get_local_ipaddr(c->sock); int local_port = c->sock == -1 ? 65536 : get_local_port(c->sock); char *remote_ipaddr = get_peer_ipaddr(c->sock); int remote_port = get_peer_port(c->sock); + int r; if (remote_port == -1) { /* Fake addr/port to appease peers that validate it (Tectia) */ @@ -1491,55 +1613,57 @@ port_open_helper(Channel *c, char *rtype) remote_port = 65535; } - snprintf(buf, sizeof buf, + free(c->remote_name); + xasprintf(&c->remote_name, "%s: listening port %d for %.100s port %d, " "connect from %.200s port %d to %.100s port %d", rtype, c->listening_port, c->path, c->host_port, remote_ipaddr, remote_port, local_ipaddr, local_port); - free(c->remote_name); - c->remote_name = xstrdup(buf); - - if (compat20) { - packet_start(SSH2_MSG_CHANNEL_OPEN); - packet_put_cstring(rtype); - packet_put_int(c->self); - packet_put_int(c->local_window_max); - packet_put_int(c->local_maxpacket); - if (strcmp(rtype, "direct-tcpip") == 0) { - /* target host, port */ - packet_put_cstring(c->path); - packet_put_int(c->host_port); - } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) { - /* target path */ - packet_put_cstring(c->path); - } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { - /* listen path */ - packet_put_cstring(c->path); - } else { - /* listen address, port */ - packet_put_cstring(c->path); - packet_put_int(local_port); + open_preamble(ssh, __func__, c, rtype); + if (strcmp(rtype, "direct-tcpip") == 0) { + /* target host, port */ + if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 || + (r = sshpkt_put_u32(ssh, c->host_port)) != 0) { + fatal("%s: channel %i: reply %s", __func__, + c->self, ssh_err(r)); } - if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { - /* reserved for future owner/mode info */ - packet_put_cstring(""); - } else { - /* originator host and port */ - packet_put_cstring(remote_ipaddr); - packet_put_int((u_int)remote_port); + } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) { + /* target path */ + if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) { + fatal("%s: channel %i: reply %s", __func__, + c->self, ssh_err(r)); + } + } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { + /* listen path */ + if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) { + fatal("%s: channel %i: reply %s", __func__, + c->self, ssh_err(r)); } - packet_send(); } else { - packet_start(SSH_MSG_PORT_OPEN); - packet_put_int(c->self); - packet_put_cstring(c->path); - packet_put_int(c->host_port); - if (packet_get_protocol_flags() & - SSH_PROTOFLAG_HOST_IN_FWD_OPEN) - packet_put_cstring(c->remote_name); - packet_send(); + /* listen address, port */ + if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 || + (r = sshpkt_put_u32(ssh, local_port)) != 0) { + fatal("%s: channel %i: reply %s", __func__, + c->self, ssh_err(r)); + } } + if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { + /* reserved for future owner/mode info */ + if ((r = sshpkt_put_cstring(ssh, "")) != 0) { + fatal("%s: channel %i: reply %s", __func__, + c->self, ssh_err(r)); + } + } else { + /* originator host and port */ + if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 || + (r = sshpkt_put_u32(ssh, (u_int)remote_port)) != 0) { + fatal("%s: channel %i: reply %s", __func__, + c->self, ssh_err(r)); + } + } + if ((r = sshpkt_send(ssh)) != 0) + fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r)); free(remote_ipaddr); free(local_ipaddr); } @@ -1558,17 +1682,17 @@ channel_set_reuseaddr(int fd) } void -channel_set_x11_refuse_time(u_int refuse_time) +channel_set_x11_refuse_time(struct ssh *ssh, u_int refuse_time) { - x11_refuse_time = refuse_time; + ssh->chanctxt->x11_refuse_time = refuse_time; } /* * This socket is listening for connections to a forwarded TCP/IP port. */ -/* ARGSUSED */ static void -channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset) +channel_post_port_listener(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { Channel *nc; struct sockaddr_storage addr; @@ -1576,360 +1700,406 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset) socklen_t addrlen; char *rtype; - if (FD_ISSET(c->sock, readset)) { - debug("Connection to port %d forwarding " - "to %.100s port %d requested.", - c->listening_port, c->path, c->host_port); + if (!FD_ISSET(c->sock, readset)) + return; - if (c->type == SSH_CHANNEL_RPORT_LISTENER) { - nextstate = SSH_CHANNEL_OPENING; - rtype = "forwarded-tcpip"; - } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) { - nextstate = SSH_CHANNEL_OPENING; - rtype = "forwarded-streamlocal@openssh.com"; - } else if (c->host_port == PORT_STREAMLOCAL) { - nextstate = SSH_CHANNEL_OPENING; - rtype = "direct-streamlocal@openssh.com"; - } else if (c->host_port == 0) { - nextstate = SSH_CHANNEL_DYNAMIC; - rtype = "dynamic-tcpip"; - } else { - nextstate = SSH_CHANNEL_OPENING; - rtype = "direct-tcpip"; - } + debug("Connection to port %d forwarding to %.100s port %d requested.", + c->listening_port, c->path, c->host_port); - addrlen = sizeof(addr); - newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); - if (newsock < 0) { - if (errno != EINTR && errno != EWOULDBLOCK && - errno != ECONNABORTED) - error("accept: %.100s", strerror(errno)); - if (errno == EMFILE || errno == ENFILE) - c->notbefore = monotime() + 1; - return; - } - if (c->host_port != PORT_STREAMLOCAL) - set_nodelay(newsock); - nc = channel_new(rtype, nextstate, newsock, newsock, -1, - c->local_window_max, c->local_maxpacket, 0, rtype, 1); - nc->listening_port = c->listening_port; - nc->host_port = c->host_port; - if (c->path != NULL) - nc->path = xstrdup(c->path); - - if (nextstate != SSH_CHANNEL_DYNAMIC) - port_open_helper(nc, rtype); + if (c->type == SSH_CHANNEL_RPORT_LISTENER) { + nextstate = SSH_CHANNEL_OPENING; + rtype = "forwarded-tcpip"; + } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) { + nextstate = SSH_CHANNEL_OPENING; + rtype = "forwarded-streamlocal@openssh.com"; + } else if (c->host_port == PORT_STREAMLOCAL) { + nextstate = SSH_CHANNEL_OPENING; + rtype = "direct-streamlocal@openssh.com"; + } else if (c->host_port == 0) { + nextstate = SSH_CHANNEL_DYNAMIC; + rtype = "dynamic-tcpip"; + } else { + nextstate = SSH_CHANNEL_OPENING; + rtype = "direct-tcpip"; } + + addrlen = sizeof(addr); + newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); + if (newsock < 0) { + if (errno != EINTR && errno != EWOULDBLOCK && + errno != ECONNABORTED) + error("accept: %.100s", strerror(errno)); + if (errno == EMFILE || errno == ENFILE) + c->notbefore = monotime() + 1; + return; + } + if (c->host_port != PORT_STREAMLOCAL) + set_nodelay(newsock); + nc = channel_new(ssh, rtype, nextstate, newsock, newsock, -1, + c->local_window_max, c->local_maxpacket, 0, rtype, 1); + nc->listening_port = c->listening_port; + nc->host_port = c->host_port; + if (c->path != NULL) + nc->path = xstrdup(c->path); + + if (nextstate != SSH_CHANNEL_DYNAMIC) + port_open_helper(ssh, nc, rtype); } /* * This is the authentication agent socket listening for connections from * clients. */ -/* ARGSUSED */ static void -channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset) +channel_post_auth_listener(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { Channel *nc; - int newsock; + int r, newsock; struct sockaddr_storage addr; socklen_t addrlen; - if (FD_ISSET(c->sock, readset)) { - addrlen = sizeof(addr); - newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); - if (newsock < 0) { - error("accept from auth socket: %.100s", - strerror(errno)); - if (errno == EMFILE || errno == ENFILE) - c->notbefore = monotime() + 1; - return; - } - nc = channel_new("accepted auth socket", - SSH_CHANNEL_OPENING, newsock, newsock, -1, - c->local_window_max, c->local_maxpacket, - 0, "accepted auth socket", 1); - if (compat20) { - packet_start(SSH2_MSG_CHANNEL_OPEN); - packet_put_cstring("auth-agent@openssh.com"); - packet_put_int(nc->self); - packet_put_int(c->local_window_max); - packet_put_int(c->local_maxpacket); - } else { - packet_start(SSH_SMSG_AGENT_OPEN); - packet_put_int(nc->self); - } - packet_send(); + if (!FD_ISSET(c->sock, readset)) + return; + + addrlen = sizeof(addr); + newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); + if (newsock < 0) { + error("accept from auth socket: %.100s", strerror(errno)); + if (errno == EMFILE || errno == ENFILE) + c->notbefore = monotime() + 1; + return; } + nc = channel_new(ssh, "accepted auth socket", + SSH_CHANNEL_OPENING, newsock, newsock, -1, + c->local_window_max, c->local_maxpacket, + 0, "accepted auth socket", 1); + open_preamble(ssh, __func__, nc, "auth-agent@openssh.com"); + if ((r = sshpkt_send(ssh)) != 0) + fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); } -/* ARGSUSED */ static void -channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset) +channel_post_connecting(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { - int err = 0, sock; + int err = 0, sock, isopen, r; socklen_t sz = sizeof(err); - if (FD_ISSET(c->sock, writeset)) { - if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) { - err = errno; - error("getsockopt SO_ERROR failed"); - } - if (err == 0) { - debug("channel %d: connected to %s port %d", - c->self, c->connect_ctx.host, c->connect_ctx.port); - channel_connect_ctx_free(&c->connect_ctx); - c->type = SSH_CHANNEL_OPEN; - if (compat20) { - packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(c->remote_id); - packet_put_int(c->self); - packet_put_int(c->local_window); - packet_put_int(c->local_maxpacket); - } else { - packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(c->remote_id); - packet_put_int(c->self); - } + if (!FD_ISSET(c->sock, writeset)) + return; + if (!c->have_remote_id) + fatal(":%s: channel %d: no remote id", __func__, c->self); + /* for rdynamic the OPEN_CONFIRMATION has been sent already */ + isopen = (c->type == SSH_CHANNEL_RDYNAMIC_FINISH); + if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) { + err = errno; + error("getsockopt SO_ERROR failed"); + } + if (err == 0) { + debug("channel %d: connected to %s port %d", + c->self, c->connect_ctx.host, c->connect_ctx.port); + channel_connect_ctx_free(&c->connect_ctx); + c->type = SSH_CHANNEL_OPEN; + if (isopen) { + /* no message necessary */ } else { - debug("channel %d: connection failed: %s", - c->self, strerror(err)); - /* Try next address, if any */ - if ((sock = connect_next(&c->connect_ctx)) > 0) { - close(c->sock); - c->sock = c->rfd = c->wfd = sock; - channel_max_fd = channel_find_maxfd(); - return; - } - /* Exhausted all addresses */ - error("connect_to %.100s port %d: failed.", - c->connect_ctx.host, c->connect_ctx.port); - channel_connect_ctx_free(&c->connect_ctx); - if (compat20) { - packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(c->remote_id); - packet_put_int(SSH2_OPEN_CONNECT_FAILED); - if (!(datafellows & SSH_BUG_OPENFAILURE)) { - packet_put_cstring(strerror(err)); - packet_put_cstring(""); - } - } else { - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(c->remote_id); - } - chan_mark_dead(c); + if ((r = sshpkt_start(ssh, + SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || + (r = sshpkt_put_u32(ssh, c->self)) != 0 || + (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || + (r = sshpkt_put_u32(ssh, c->local_maxpacket)) + != 0) + fatal("%s: channel %i: confirm: %s", __func__, + c->self, ssh_err(r)); + if ((r = sshpkt_send(ssh)) != 0) + fatal("%s: channel %i: %s", __func__, c->self, + ssh_err(r)); + } + } else { + debug("channel %d: connection failed: %s", + c->self, strerror(err)); + /* Try next address, if any */ + if ((sock = connect_next(&c->connect_ctx)) > 0) { + close(c->sock); + c->sock = c->rfd = c->wfd = sock; + channel_find_maxfd(ssh->chanctxt); + return; + } + /* Exhausted all addresses */ + error("connect_to %.100s port %d: failed.", + c->connect_ctx.host, c->connect_ctx.port); + channel_connect_ctx_free(&c->connect_ctx); + if (isopen) { + rdynamic_close(ssh, c); + } else { + if ((r = sshpkt_start(ssh, + SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || + (r = sshpkt_put_u32(ssh, SSH2_OPEN_CONNECT_FAILED)) + != 0) + fatal("%s: channel %i: failure: %s", __func__, + c->self, ssh_err(r)); + if ((datafellows & SSH_BUG_OPENFAILURE) == 0 && + ((r = sshpkt_put_cstring(ssh, strerror(err))) != 0 || + (r = sshpkt_put_cstring(ssh, "")) != 0)) + fatal("%s: channel %i: failure: %s", __func__, + c->self, ssh_err(r)); + if ((r = sshpkt_send(ssh)) != 0) + fatal("%s: channel %i: %s", __func__, c->self, + ssh_err(r)); + chan_mark_dead(ssh, c); } - packet_send(); } } -/* ARGSUSED */ static int -channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset) +channel_handle_rfd(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { char buf[CHAN_RBUF]; - int len, force; + ssize_t len; + int r, force; force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED; - if (c->rfd != -1 && (force || FD_ISSET(c->rfd, readset))) { - errno = 0; - len = read(c->rfd, buf, sizeof(buf)); - if (len < 0 && (errno == EINTR || - ((errno == EAGAIN || errno == EWOULDBLOCK) && !force))) - return 1; + + if (c->rfd == -1 || (!force && !FD_ISSET(c->rfd, readset))) + return 1; + + errno = 0; + len = read(c->rfd, buf, sizeof(buf)); + if (len < 0 && (errno == EINTR || + ((errno == EAGAIN || errno == EWOULDBLOCK) && !force))) + return 1; #ifndef PTY_ZEROREAD - if (len <= 0) { + if (len <= 0) { #else - if ((!c->isatty && len <= 0) || - (c->isatty && (len < 0 || (len == 0 && errno != 0)))) { + if ((!c->isatty && len <= 0) || + (c->isatty && (len < 0 || (len == 0 && errno != 0)))) { #endif - debug2("channel %d: read<=0 rfd %d len %d", - c->self, c->rfd, len); - if (c->type != SSH_CHANNEL_OPEN) { - debug2("channel %d: not open", c->self); - chan_mark_dead(c); - return -1; - } else if (compat13) { - buffer_clear(&c->output); - c->type = SSH_CHANNEL_INPUT_DRAINING; - debug2("channel %d: input draining.", c->self); - } else { - chan_read_failed(c); - } + debug2("channel %d: read<=0 rfd %d len %zd", + c->self, c->rfd, len); + if (c->type != SSH_CHANNEL_OPEN) { + debug2("channel %d: not open", c->self); + chan_mark_dead(ssh, c); return -1; - } - if (c->input_filter != NULL) { - if (c->input_filter(c, buf, len) == -1) { - debug2("channel %d: filter stops", c->self); - chan_read_failed(c); - } - } else if (c->datagram) { - buffer_put_string(&c->input, buf, len); } else { - buffer_append(&c->input, buf, len); + chan_read_failed(ssh, c); } + return -1; + } + if (c->input_filter != NULL) { + if (c->input_filter(ssh, c, buf, len) == -1) { + debug2("channel %d: filter stops", c->self); + chan_read_failed(ssh, c); + } + } else if (c->datagram) { + if ((r = sshbuf_put_string(c->input, buf, len)) != 0) + fatal("%s: channel %d: put datagram: %s", __func__, + c->self, ssh_err(r)); + } else if ((r = sshbuf_put(c->input, buf, len)) != 0) { + fatal("%s: channel %d: put data: %s", __func__, + c->self, ssh_err(r)); } return 1; } -/* ARGSUSED */ static int -channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset) +channel_handle_wfd(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { struct termios tio; - u_char *data = NULL, *buf; - u_int dlen, olen = 0; - int len; + u_char *data = NULL, *buf; /* XXX const; need filter API change */ + size_t dlen, olen = 0; + int r, len; + + if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) || + sshbuf_len(c->output) == 0) + return 1; /* Send buffered output data to the socket. */ - if (c->wfd != -1 && - FD_ISSET(c->wfd, writeset) && - buffer_len(&c->output) > 0) { - olen = buffer_len(&c->output); - if (c->output_filter != NULL) { - if ((buf = c->output_filter(c, &data, &dlen)) == NULL) { - debug2("channel %d: filter stops", c->self); - if (c->type != SSH_CHANNEL_OPEN) - chan_mark_dead(c); - else - chan_write_failed(c); - return -1; - } - } else if (c->datagram) { - buf = data = buffer_get_string(&c->output, &dlen); - } else { - buf = data = buffer_ptr(&c->output); - dlen = buffer_len(&c->output); - } - - if (c->datagram) { - /* ignore truncated writes, datagrams might get lost */ - len = write(c->wfd, buf, dlen); - free(data); - if (len < 0 && (errno == EINTR || errno == EAGAIN || - errno == EWOULDBLOCK)) - return 1; - if (len <= 0) { - if (c->type != SSH_CHANNEL_OPEN) - chan_mark_dead(c); - else - chan_write_failed(c); - return -1; - } - goto out; - } -#ifdef _AIX - /* XXX: Later AIX versions can't push as much data to tty */ - if (compat20 && c->wfd_isatty) - dlen = MIN(dlen, 8*1024); -#endif - - len = write(c->wfd, buf, dlen); - if (len < 0 && - (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) - return 1; - if (len <= 0) { - if (c->type != SSH_CHANNEL_OPEN) { - debug2("channel %d: not open", c->self); - chan_mark_dead(c); - return -1; - } else if (compat13) { - buffer_clear(&c->output); - debug2("channel %d: input draining.", c->self); - c->type = SSH_CHANNEL_INPUT_DRAINING; - } else { - chan_write_failed(c); - } + olen = sshbuf_len(c->output); + if (c->output_filter != NULL) { + if ((buf = c->output_filter(ssh, c, &data, &dlen)) == NULL) { + debug2("channel %d: filter stops", c->self); + if (c->type != SSH_CHANNEL_OPEN) + chan_mark_dead(ssh, c); + else + chan_write_failed(ssh, c); return -1; } -#ifndef BROKEN_TCGETATTR_ICANON - if (compat20 && c->isatty && dlen >= 1 && buf[0] != '\r') { - if (tcgetattr(c->wfd, &tio) == 0 && - !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { - /* - * Simulate echo to reduce the impact of - * traffic analysis. We need to match the - * size of a SSH2_MSG_CHANNEL_DATA message - * (4 byte channel id + buf) - */ - packet_send_ignore(4 + len); - packet_send(); - } - } + } else if (c->datagram) { + if ((r = sshbuf_get_string(c->output, &data, &dlen)) != 0) + fatal("%s: channel %d: get datagram: %s", __func__, + c->self, ssh_err(r)); + buf = data; + } else { + buf = data = sshbuf_mutable_ptr(c->output); + dlen = sshbuf_len(c->output); + } + + if (c->datagram) { + /* ignore truncated writes, datagrams might get lost */ + len = write(c->wfd, buf, dlen); + free(data); + if (len < 0 && (errno == EINTR || errno == EAGAIN || + errno == EWOULDBLOCK)) + return 1; + if (len <= 0) + goto write_fail; + goto out; + } + +#ifdef _AIX + /* XXX: Later AIX versions can't push as much data to tty */ + if (c->wfd_isatty) + dlen = MIN(dlen, 8*1024); #endif - buffer_consume(&c->output, len); + + len = write(c->wfd, buf, dlen); + if (len < 0 && + (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) + return 1; + if (len <= 0) { + write_fail: + if (c->type != SSH_CHANNEL_OPEN) { + debug2("channel %d: not open", c->self); + chan_mark_dead(ssh, c); + return -1; + } else { + chan_write_failed(ssh, c); + } + return -1; + } +#ifndef BROKEN_TCGETATTR_ICANON + if (c->isatty && dlen >= 1 && buf[0] != '\r') { + if (tcgetattr(c->wfd, &tio) == 0 && + !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { + /* + * Simulate echo to reduce the impact of + * traffic analysis. We need to match the + * size of a SSH2_MSG_CHANNEL_DATA message + * (4 byte channel id + buf) + */ + if ((r = sshpkt_msg_ignore(ssh, 4+len)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("%s: channel %d: ignore: %s", + __func__, c->self, ssh_err(r)); + } + } +#endif /* BROKEN_TCGETATTR_ICANON */ + if ((r = sshbuf_consume(c->output, len)) != 0) { + fatal("%s: channel %d: consume: %s", + __func__, c->self, ssh_err(r)); } out: - if (compat20 && olen > 0) - c->local_consumed += olen - buffer_len(&c->output); + c->local_consumed += olen - sshbuf_len(c->output); + return 1; } static int -channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset) +channel_handle_efd_write(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) +{ + int r; + ssize_t len; + + if (!FD_ISSET(c->efd, writeset) || sshbuf_len(c->extended) == 0) + return 1; + + len = write(c->efd, sshbuf_ptr(c->extended), + sshbuf_len(c->extended)); + debug2("channel %d: written %zd to efd %d", c->self, len, c->efd); + if (len < 0 && (errno == EINTR || errno == EAGAIN || + errno == EWOULDBLOCK)) + return 1; + if (len <= 0) { + debug2("channel %d: closing write-efd %d", c->self, c->efd); + channel_close_fd(ssh, &c->efd); + } else { + if ((r = sshbuf_consume(c->extended, len)) != 0) { + fatal("%s: channel %d: consume: %s", + __func__, c->self, ssh_err(r)); + } + c->local_consumed += len; + } + return 1; +} + +static int +channel_handle_efd_read(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { char buf[CHAN_RBUF]; - int len; + int r; + ssize_t len; -/** XXX handle drain efd, too */ - if (c->efd != -1) { - if (c->extended_usage == CHAN_EXTENDED_WRITE && - FD_ISSET(c->efd, writeset) && - buffer_len(&c->extended) > 0) { - len = write(c->efd, buffer_ptr(&c->extended), - buffer_len(&c->extended)); - debug2("channel %d: written %d to efd %d", - c->self, len, c->efd); - if (len < 0 && (errno == EINTR || errno == EAGAIN || - errno == EWOULDBLOCK)) - return 1; - if (len <= 0) { - debug2("channel %d: closing write-efd %d", - c->self, c->efd); - channel_close_fd(&c->efd); - } else { - buffer_consume(&c->extended, len); - c->local_consumed += len; - } - } else if (c->efd != -1 && - (c->extended_usage == CHAN_EXTENDED_READ || - c->extended_usage == CHAN_EXTENDED_IGNORE) && - (c->detach_close || FD_ISSET(c->efd, readset))) { - len = read(c->efd, buf, sizeof(buf)); - debug2("channel %d: read %d from efd %d", - c->self, len, c->efd); - if (len < 0 && (errno == EINTR || ((errno == EAGAIN || - errno == EWOULDBLOCK) && !c->detach_close))) - return 1; - if (len <= 0) { - debug2("channel %d: closing read-efd %d", - c->self, c->efd); - channel_close_fd(&c->efd); - } else { - if (c->extended_usage == CHAN_EXTENDED_IGNORE) { - debug3("channel %d: discard efd", - c->self); - } else - buffer_append(&c->extended, buf, len); - } + if (!c->detach_close && !FD_ISSET(c->efd, readset)) + return 1; + + len = read(c->efd, buf, sizeof(buf)); + debug2("channel %d: read %zd from efd %d", c->self, len, c->efd); + if (len < 0 && (errno == EINTR || ((errno == EAGAIN || + errno == EWOULDBLOCK) && !c->detach_close))) + return 1; + if (len <= 0) { + debug2("channel %d: closing read-efd %d", + c->self, c->efd); + channel_close_fd(ssh, &c->efd); + } else { + if (c->extended_usage == CHAN_EXTENDED_IGNORE) { + debug3("channel %d: discard efd", + c->self); + } else if ((r = sshbuf_put(c->extended, buf, len)) != 0) { + fatal("%s: channel %d: append: %s", + __func__, c->self, ssh_err(r)); } } return 1; } static int -channel_check_window(Channel *c) +channel_handle_efd(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { + if (c->efd == -1) + return 1; + + /** XXX handle drain efd, too */ + + if (c->extended_usage == CHAN_EXTENDED_WRITE) + return channel_handle_efd_write(ssh, c, readset, writeset); + else if (c->extended_usage == CHAN_EXTENDED_READ || + c->extended_usage == CHAN_EXTENDED_IGNORE) + return channel_handle_efd_read(ssh, c, readset, writeset); + + return 1; +} + +static int +channel_check_window(struct ssh *ssh, Channel *c) +{ + int r; + if (c->type == SSH_CHANNEL_OPEN && !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) && ((c->local_window_max - c->local_window > c->local_maxpacket*3) || c->local_window < c->local_window_max/2) && c->local_consumed > 0) { - packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); - packet_put_int(c->remote_id); - packet_put_int(c->local_consumed); - packet_send(); + if (!c->have_remote_id) + fatal(":%s: channel %d: no remote id", + __func__, c->self); + if ((r = sshpkt_start(ssh, + SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || + (r = sshpkt_put_u32(ssh, c->local_consumed)) != 0 || + (r = sshpkt_send(ssh)) != 0) { + fatal("%s: channel %i: %s", __func__, + c->self, ssh_err(r)); + } debug2("channel %d: window %d sent adjust %d", c->self, c->local_window, c->local_consumed); @@ -1940,90 +2110,112 @@ channel_check_window(Channel *c) } static void -channel_post_open(Channel *c, fd_set *readset, fd_set *writeset) +channel_post_open(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { - channel_handle_rfd(c, readset, writeset); - channel_handle_wfd(c, readset, writeset); - if (!compat20) - return; - channel_handle_efd(c, readset, writeset); - channel_check_window(c); + channel_handle_rfd(ssh, c, readset, writeset); + channel_handle_wfd(ssh, c, readset, writeset); + channel_handle_efd(ssh, c, readset, writeset); + channel_check_window(ssh, c); } static u_int -read_mux(Channel *c, u_int need) +read_mux(struct ssh *ssh, Channel *c, u_int need) { char buf[CHAN_RBUF]; - int len; + ssize_t len; u_int rlen; + int r; - if (buffer_len(&c->input) < need) { - rlen = need - buffer_len(&c->input); + if (sshbuf_len(c->input) < need) { + rlen = need - sshbuf_len(c->input); len = read(c->rfd, buf, MINIMUM(rlen, CHAN_RBUF)); if (len < 0 && (errno == EINTR || errno == EAGAIN)) - return buffer_len(&c->input); + return sshbuf_len(c->input); if (len <= 0) { - debug2("channel %d: ctl read<=0 rfd %d len %d", + debug2("channel %d: ctl read<=0 rfd %d len %zd", c->self, c->rfd, len); - chan_read_failed(c); + chan_read_failed(ssh, c); return 0; - } else - buffer_append(&c->input, buf, len); + } else if ((r = sshbuf_put(c->input, buf, len)) != 0) { + fatal("%s: channel %d: append: %s", + __func__, c->self, ssh_err(r)); + } } - return buffer_len(&c->input); + return sshbuf_len(c->input); } static void -channel_post_mux_client(Channel *c, fd_set *readset, fd_set *writeset) +channel_post_mux_client_read(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { u_int need; - ssize_t len; - if (!compat20) - fatal("%s: entered with !compat20", __func__); + if (c->rfd == -1 || !FD_ISSET(c->rfd, readset)) + return; + if (c->istate != CHAN_INPUT_OPEN && c->istate != CHAN_INPUT_WAIT_DRAIN) + return; + if (c->mux_pause) + return; - if (c->rfd != -1 && !c->mux_pause && FD_ISSET(c->rfd, readset) && - (c->istate == CHAN_INPUT_OPEN || - c->istate == CHAN_INPUT_WAIT_DRAIN)) { - /* - * Don't not read past the precise end of packets to - * avoid disrupting fd passing. - */ - if (read_mux(c, 4) < 4) /* read header */ - return; - need = get_u32(buffer_ptr(&c->input)); + /* + * Don't not read past the precise end of packets to + * avoid disrupting fd passing. + */ + if (read_mux(ssh, c, 4) < 4) /* read header */ + return; + /* XXX sshbuf_peek_u32 */ + need = PEEK_U32(sshbuf_ptr(c->input)); #define CHANNEL_MUX_MAX_PACKET (256 * 1024) - if (need > CHANNEL_MUX_MAX_PACKET) { - debug2("channel %d: packet too big %u > %u", - c->self, CHANNEL_MUX_MAX_PACKET, need); - chan_rcvd_oclose(c); - return; - } - if (read_mux(c, need + 4) < need + 4) /* read body */ - return; - if (c->mux_rcb(c) != 0) { - debug("channel %d: mux_rcb failed", c->self); - chan_mark_dead(c); - return; - } + if (need > CHANNEL_MUX_MAX_PACKET) { + debug2("channel %d: packet too big %u > %u", + c->self, CHANNEL_MUX_MAX_PACKET, need); + chan_rcvd_oclose(ssh, c); + return; } - - if (c->wfd != -1 && FD_ISSET(c->wfd, writeset) && - buffer_len(&c->output) > 0) { - len = write(c->wfd, buffer_ptr(&c->output), - buffer_len(&c->output)); - if (len < 0 && (errno == EINTR || errno == EAGAIN)) - return; - if (len <= 0) { - chan_mark_dead(c); - return; - } - buffer_consume(&c->output, len); + if (read_mux(ssh, c, need + 4) < need + 4) /* read body */ + return; + if (c->mux_rcb(ssh, c) != 0) { + debug("channel %d: mux_rcb failed", c->self); + chan_mark_dead(ssh, c); + return; } } static void -channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset) +channel_post_mux_client_write(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) +{ + ssize_t len; + int r; + + if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) || + sshbuf_len(c->output) == 0) + return; + + len = write(c->wfd, sshbuf_ptr(c->output), sshbuf_len(c->output)); + if (len < 0 && (errno == EINTR || errno == EAGAIN)) + return; + if (len <= 0) { + chan_mark_dead(ssh, c); + return; + } + if ((r = sshbuf_consume(c->output, len)) != 0) + fatal("%s: channel %d: consume: %s", __func__, + c->self, ssh_err(r)); +} + +static void +channel_post_mux_client(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) +{ + channel_post_mux_client_read(ssh, c, readset, writeset); + channel_post_mux_client_write(ssh, c, readset, writeset); +} + +static void +channel_post_mux_listener(struct ssh *ssh, Channel *c, + fd_set *readset, fd_set *writeset) { Channel *nc; struct sockaddr_storage addr; @@ -2062,166 +2254,100 @@ channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset) close(newsock); return; } - nc = channel_new("multiplex client", SSH_CHANNEL_MUX_CLIENT, + nc = channel_new(ssh, "multiplex client", SSH_CHANNEL_MUX_CLIENT, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, "mux-control", 1); nc->mux_rcb = c->mux_rcb; - debug3("%s: new mux channel %d fd %d", __func__, - nc->self, nc->sock); + debug3("%s: new mux channel %d fd %d", __func__, nc->self, nc->sock); /* establish state */ - nc->mux_rcb(nc); + nc->mux_rcb(ssh, nc); /* mux state transitions must not elicit protocol messages */ nc->flags |= CHAN_LOCAL; } -/* ARGSUSED */ static void -channel_post_output_drain_13(Channel *c, fd_set *readset, fd_set *writeset) +channel_handler_init(struct ssh_channels *sc) { - int len; + chan_fn **pre, **post; - /* Send buffered output data to the socket. */ - if (FD_ISSET(c->sock, writeset) && buffer_len(&c->output) > 0) { - len = write(c->sock, buffer_ptr(&c->output), - buffer_len(&c->output)); - if (len <= 0) - buffer_clear(&c->output); - else - buffer_consume(&c->output, len); - } -} + if ((pre = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*pre))) == NULL || + (post = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*post))) == NULL) + fatal("%s: allocation failed", __func__); -static void -channel_handler_init_20(void) -{ - channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open; - channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; - channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; - channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; - channel_pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client; + pre[SSH_CHANNEL_OPEN] = &channel_pre_open; + pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; + pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; + pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; + pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener; + pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener; + pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; + pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; + pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; + pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; + pre[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_pre_connecting; + pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener; + pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client; - channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; - channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; - channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; - channel_post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener; - channel_post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener; - channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; - channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; - channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; - channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; - channel_post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener; - channel_post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client; -} + post[SSH_CHANNEL_OPEN] = &channel_post_open; + post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; + post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; + post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener; + post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener; + post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; + post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; + post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; + post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; + post[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_post_connecting; + post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener; + post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client; -static void -channel_handler_init_13(void) -{ - channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_13; - channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open_13; - channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining; - channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining; - channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; - channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; - - channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; - channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; - channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; - channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; - channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13; - channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; - channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; -} - -static void -channel_handler_init_15(void) -{ - channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open; - channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; - channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; - channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; - channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; - - channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; - channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; - channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; - channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; - channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; - channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; -} - -static void -channel_handler_init(void) -{ - int i; - - for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) { - channel_pre[i] = NULL; - channel_post[i] = NULL; - } - if (compat20) - channel_handler_init_20(); - else if (compat13) - channel_handler_init_13(); - else - channel_handler_init_15(); + sc->channel_pre = pre; + sc->channel_post = post; } /* gc dead channels */ static void -channel_garbage_collect(Channel *c) +channel_garbage_collect(struct ssh *ssh, Channel *c) { if (c == NULL) return; if (c->detach_user != NULL) { - if (!chan_is_dead(c, c->detach_close)) + if (!chan_is_dead(ssh, c, c->detach_close)) return; debug2("channel %d: gc: notify user", c->self); - c->detach_user(c->self, NULL); + c->detach_user(ssh, c->self, NULL); /* if we still have a callback */ if (c->detach_user != NULL) return; debug2("channel %d: gc: user detached", c->self); } - if (!chan_is_dead(c, 1)) + if (!chan_is_dead(ssh, c, 1)) return; debug2("channel %d: garbage collecting", c->self); - channel_free(c); + channel_free(ssh, c); } +enum channel_table { CHAN_PRE, CHAN_POST }; + static void -channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset, - time_t *unpause_secs) +channel_handler(struct ssh *ssh, int table, + fd_set *readset, fd_set *writeset, time_t *unpause_secs) { - static int did_init = 0; + struct ssh_channels *sc = ssh->chanctxt; + chan_fn **ftab = table == CHAN_PRE ? sc->channel_pre : sc->channel_post; u_int i, oalloc; Channel *c; time_t now; - if (!did_init) { - channel_handler_init(); - did_init = 1; - } now = monotime(); if (unpause_secs != NULL) *unpause_secs = 0; - for (i = 0, oalloc = channels_alloc; i < oalloc; i++) { - c = channels[i]; + for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) { + c = sc->channels[i]; if (c == NULL) continue; if (c->delayed) { - if (ftab == channel_pre) + if (table == CHAN_PRE) c->delayed = 0; else continue; @@ -2231,7 +2357,7 @@ channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset, * Run handlers that are not paused. */ if (c->notbefore <= now) - (*ftab[c->type])(c, readset, writeset); + (*ftab[c->type])(ssh, c, readset, writeset); else if (unpause_secs != NULL) { /* * Collect the time that the earliest @@ -2245,24 +2371,47 @@ channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset, *unpause_secs = c->notbefore - now; } } - channel_garbage_collect(c); + channel_garbage_collect(ssh, c); } if (unpause_secs != NULL && *unpause_secs != 0) debug3("%s: first channel unpauses in %d seconds", __func__, (int)*unpause_secs); } +/* + * Create sockets before allocating the select bitmasks. + * This is necessary for things that need to happen after reading + * the network-input but before channel_prepare_select(). + */ +static void +channel_before_prepare_select(struct ssh *ssh) +{ + struct ssh_channels *sc = ssh->chanctxt; + Channel *c; + u_int i, oalloc; + + for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) { + c = sc->channels[i]; + if (c == NULL) + continue; + if (c->type == SSH_CHANNEL_RDYNAMIC_OPEN) + channel_before_prepare_select_rdynamic(ssh, c); + } +} + /* * Allocate/update select bitmasks and add any bits relevant to channels in * select bitmasks. */ void -channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp, - u_int *nallocp, time_t *minwait_secs, int rekeying) +channel_prepare_select(struct ssh *ssh, fd_set **readsetp, fd_set **writesetp, + int *maxfdp, u_int *nallocp, time_t *minwait_secs) { u_int n, sz, nfdset; - n = MAXIMUM(*maxfdp, channel_max_fd); + channel_before_prepare_select(ssh); /* might update channel_max_fd */ + + n = MAXIMUM(*maxfdp, ssh->chanctxt->channel_max_fd); nfdset = howmany(n+1, NFDBITS); /* Explicitly test here, because xrealloc isn't always called */ @@ -2280,8 +2429,8 @@ channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp, memset(*readsetp, 0, sz); memset(*writesetp, 0, sz); - if (!rekeying) - channel_handler(channel_pre, *readsetp, *writesetp, + if (!ssh_packet_is_rekeying(ssh)) + channel_handler(ssh, CHAN_PRE, *readsetp, *writesetp, minwait_secs); } @@ -2290,21 +2439,136 @@ channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp, * events pending. */ void -channel_after_select(fd_set *readset, fd_set *writeset) +channel_after_select(struct ssh *ssh, fd_set *readset, fd_set *writeset) { - channel_handler(channel_post, readset, writeset, NULL); + channel_handler(ssh, CHAN_POST, readset, writeset, NULL); } +/* + * Enqueue data for channels with open or draining c->input. + */ +static void +channel_output_poll_input_open(struct ssh *ssh, Channel *c) +{ + size_t len, plen; + const u_char *pkt; + int r; + + if ((len = sshbuf_len(c->input)) == 0) { + if (c->istate == CHAN_INPUT_WAIT_DRAIN) { + /* + * input-buffer is empty and read-socket shutdown: + * tell peer, that we will not send more data: + * send IEOF. + * hack for extended data: delay EOF if EFD still + * in use. + */ + if (CHANNEL_EFD_INPUT_ACTIVE(c)) + debug2("channel %d: " + "ibuf_empty delayed efd %d/(%zu)", + c->self, c->efd, sshbuf_len(c->extended)); + else + chan_ibuf_empty(ssh, c); + } + return; + } + + if (!c->have_remote_id) + fatal(":%s: channel %d: no remote id", __func__, c->self); + + if (c->datagram) { + /* Check datagram will fit; drop if not */ + if ((r = sshbuf_get_string_direct(c->input, &pkt, &plen)) != 0) + fatal("%s: channel %d: get datagram: %s", __func__, + c->self, ssh_err(r)); + /* + * XXX this does tail-drop on the datagram queue which is + * usually suboptimal compared to head-drop. Better to have + * backpressure at read time? (i.e. read + discard) + */ + if (plen > c->remote_window || plen > c->remote_maxpacket) { + debug("channel %d: datagram too big", c->self); + return; + } + /* Enqueue it */ + if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || + (r = sshpkt_put_string(ssh, pkt, plen)) != 0 || + (r = sshpkt_send(ssh)) != 0) { + fatal("%s: channel %i: datagram: %s", __func__, + c->self, ssh_err(r)); + } + c->remote_window -= plen; + return; + } + + /* Enqueue packet for buffered data. */ + if (len > c->remote_window) + len = c->remote_window; + if (len > c->remote_maxpacket) + len = c->remote_maxpacket; + if (len == 0) + return; + if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || + (r = sshpkt_put_string(ssh, sshbuf_ptr(c->input), len)) != 0 || + (r = sshpkt_send(ssh)) != 0) { + fatal("%s: channel %i: data: %s", __func__, + c->self, ssh_err(r)); + } + if ((r = sshbuf_consume(c->input, len)) != 0) + fatal("%s: channel %i: consume: %s", __func__, + c->self, ssh_err(r)); + c->remote_window -= len; +} + +/* + * Enqueue data for channels with open c->extended in read mode. + */ +static void +channel_output_poll_extended_read(struct ssh *ssh, Channel *c) +{ + size_t len; + int r; + + if ((len = sshbuf_len(c->extended)) == 0) + return; + + debug2("channel %d: rwin %u elen %zu euse %d", c->self, + c->remote_window, sshbuf_len(c->extended), c->extended_usage); + if (len > c->remote_window) + len = c->remote_window; + if (len > c->remote_maxpacket) + len = c->remote_maxpacket; + if (len == 0) + return; + if (!c->have_remote_id) + fatal(":%s: channel %d: no remote id", __func__, c->self); + if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || + (r = sshpkt_put_u32(ssh, SSH2_EXTENDED_DATA_STDERR)) != 0 || + (r = sshpkt_put_string(ssh, sshbuf_ptr(c->extended), len)) != 0 || + (r = sshpkt_send(ssh)) != 0) { + fatal("%s: channel %i: data: %s", __func__, + c->self, ssh_err(r)); + } + if ((r = sshbuf_consume(c->extended, len)) != 0) + fatal("%s: channel %i: consume: %s", __func__, + c->self, ssh_err(r)); + c->remote_window -= len; + debug2("channel %d: sent ext data %zu", c->self, len); +} /* If there is data to send to the connection, enqueue some of it now. */ void -channel_output_poll(void) +channel_output_poll(struct ssh *ssh) { + struct ssh_channels *sc = ssh->chanctxt; Channel *c; - u_int i, len; + u_int i; - for (i = 0; i < channels_alloc; i++) { - c = channels[i]; + for (i = 0; i < sc->channels_alloc; i++) { + c = sc->channels[i]; if (c == NULL) continue; @@ -2312,113 +2576,23 @@ channel_output_poll(void) * We are only interested in channels that can have buffered * incoming data. */ - if (compat13) { - if (c->type != SSH_CHANNEL_OPEN && - c->type != SSH_CHANNEL_INPUT_DRAINING) - continue; - } else { - if (c->type != SSH_CHANNEL_OPEN) - continue; - } - if (compat20 && - (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { + if (c->type != SSH_CHANNEL_OPEN) + continue; + if ((c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { /* XXX is this true? */ - debug3("channel %d: will not send data after close", c->self); + debug3("channel %d: will not send data after close", + c->self); continue; } /* Get the amount of buffered data for this channel. */ - if ((c->istate == CHAN_INPUT_OPEN || - c->istate == CHAN_INPUT_WAIT_DRAIN) && - (len = buffer_len(&c->input)) > 0) { - if (c->datagram) { - if (len > 0) { - u_char *data; - u_int dlen; - - data = buffer_get_string(&c->input, - &dlen); - if (dlen > c->remote_window || - dlen > c->remote_maxpacket) { - debug("channel %d: datagram " - "too big for channel", - c->self); - free(data); - continue; - } - packet_start(SSH2_MSG_CHANNEL_DATA); - packet_put_int(c->remote_id); - packet_put_string(data, dlen); - packet_send(); - c->remote_window -= dlen; - free(data); - } - continue; - } - /* - * Send some data for the other side over the secure - * connection. - */ - if (compat20) { - if (len > c->remote_window) - len = c->remote_window; - if (len > c->remote_maxpacket) - len = c->remote_maxpacket; - } else { - if (packet_is_interactive()) { - if (len > 1024) - len = 512; - } else { - /* Keep the packets at reasonable size. */ - if (len > packet_get_maxsize()/2) - len = packet_get_maxsize()/2; - } - } - if (len > 0) { - packet_start(compat20 ? - SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA); - packet_put_int(c->remote_id); - packet_put_string(buffer_ptr(&c->input), len); - packet_send(); - buffer_consume(&c->input, len); - c->remote_window -= len; - } - } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) { - if (compat13) - fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3"); - /* - * input-buffer is empty and read-socket shutdown: - * tell peer, that we will not send more data: send IEOF. - * hack for extended data: delay EOF if EFD still in use. - */ - if (CHANNEL_EFD_INPUT_ACTIVE(c)) - debug2("channel %d: ibuf_empty delayed efd %d/(%d)", - c->self, c->efd, buffer_len(&c->extended)); - else - chan_ibuf_empty(c); - } + if (c->istate == CHAN_INPUT_OPEN || + c->istate == CHAN_INPUT_WAIT_DRAIN) + channel_output_poll_input_open(ssh, c); /* Send extended data, i.e. stderr */ - if (compat20 && - !(c->flags & CHAN_EOF_SENT) && - c->remote_window > 0 && - (len = buffer_len(&c->extended)) > 0 && - c->extended_usage == CHAN_EXTENDED_READ) { - debug2("channel %d: rwin %u elen %u euse %d", - c->self, c->remote_window, buffer_len(&c->extended), - c->extended_usage); - if (len > c->remote_window) - len = c->remote_window; - if (len > c->remote_maxpacket) - len = c->remote_maxpacket; - packet_start(SSH2_MSG_CHANNEL_EXTENDED_DATA); - packet_put_int(c->remote_id); - packet_put_int(SSH2_EXTENDED_DATA_STDERR); - packet_put_string(buffer_ptr(&c->extended), len); - packet_send(); - buffer_consume(&c->extended, len); - c->remote_window -= len; - debug2("channel %d: sent ext data %d", c->self, len); - } + if (!(c->flags & CHAN_EOF_SENT) && + c->extended_usage == CHAN_EXTENDED_READ) + channel_output_poll_extended_read(ssh, c); } } @@ -2463,20 +2637,19 @@ channel_output_poll(void) * on channel creation. */ int -channel_proxy_downstream(Channel *downstream) +channel_proxy_downstream(struct ssh *ssh, Channel *downstream) { Channel *c = NULL; - struct ssh *ssh = active_state; struct sshbuf *original = NULL, *modified = NULL; const u_char *cp; char *ctype = NULL, *listen_host = NULL; u_char type; size_t have; - int ret = -1, r, idx; + int ret = -1, r; u_int id, remote_id, listen_port; - /* sshbuf_dump(&downstream->input, stderr); */ - if ((r = sshbuf_get_string_direct(&downstream->input, &cp, &have)) + /* sshbuf_dump(downstream->input, stderr); */ + if ((r = sshbuf_get_string_direct(downstream->input, &cp, &have)) != 0) { error("%s: malformed message: %s", __func__, ssh_err(r)); return -1; @@ -2505,7 +2678,7 @@ channel_proxy_downstream(Channel *downstream) error("%s: parse error %s", __func__, ssh_err(r)); goto out; } - c = channel_new("mux proxy", SSH_CHANNEL_MUX_PROXY, + c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY, -1, -1, -1, 0, 0, 0, ctype, 1); c->mux_ctx = downstream; /* point to mux client */ c->mux_downstream_id = id; /* original downstream id */ @@ -2513,7 +2686,7 @@ channel_proxy_downstream(Channel *downstream) (r = sshbuf_put_u32(modified, c->self)) != 0 || (r = sshbuf_putb(modified, original)) != 0) { error("%s: compose error %s", __func__, ssh_err(r)); - channel_free(c); + channel_free(ssh, c); goto out; } break; @@ -2532,16 +2705,17 @@ channel_proxy_downstream(Channel *downstream) error("%s: parse error %s", __func__, ssh_err(r)); goto out; } - c = channel_new("mux proxy", SSH_CHANNEL_MUX_PROXY, + c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY, -1, -1, -1, 0, 0, 0, "mux-down-connect", 1); c->mux_ctx = downstream; /* point to mux client */ c->mux_downstream_id = id; c->remote_id = remote_id; + c->have_remote_id = 1; if ((r = sshbuf_put_u32(modified, remote_id)) != 0 || (r = sshbuf_put_u32(modified, c->self)) != 0 || (r = sshbuf_putb(modified, original)) != 0) { error("%s: compose error %s", __func__, ssh_err(r)); - channel_free(c); + channel_free(ssh, c); goto out; } break; @@ -2570,23 +2744,17 @@ channel_proxy_downstream(Channel *downstream) goto out; } /* Record that connection to this host/port is permitted. */ - permitted_opens = xreallocarray(permitted_opens, - num_permitted_opens + 1, sizeof(*permitted_opens)); - idx = num_permitted_opens++; - permitted_opens[idx].host_to_connect = xstrdup(""); - permitted_opens[idx].port_to_connect = -1; - permitted_opens[idx].listen_host = listen_host; - permitted_opens[idx].listen_port = (int)listen_port; - permitted_opens[idx].downstream = downstream; + fwd_perm_list_add(ssh, FWDPERM_USER, "", -1, + listen_host, NULL, (int)listen_port, downstream); listen_host = NULL; break; case SSH2_MSG_CHANNEL_CLOSE: if (have < 4) break; remote_id = PEEK_U32(cp); - if ((c = channel_by_remote_id(remote_id)) != NULL) { + if ((c = channel_by_remote_id(ssh, remote_id)) != NULL) { if (c->flags & CHAN_CLOSE_RCVD) - channel_free(c); + channel_free(ssh, c); else c->flags |= CHAN_CLOSE_SENT; } @@ -2623,9 +2791,8 @@ channel_proxy_downstream(Channel *downstream) * replaces local (proxy) channel ID with downstream channel ID. */ int -channel_proxy_upstream(Channel *c, int type, u_int32_t seq, void *ctxt) +channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = active_state; struct sshbuf *b = NULL; Channel *downstream; const u_char *cp = NULL; @@ -2674,7 +2841,7 @@ channel_proxy_upstream(Channel *c, int type, u_int32_t seq, void *ctxt) (r = sshbuf_put_u8(b, type)) != 0 || (r = sshbuf_put_u32(b, c->mux_downstream_id)) != 0 || (r = sshbuf_put(b, cp, len)) != 0 || - (r = sshbuf_put_stringb(&downstream->output, b)) != 0) { + (r = sshbuf_put_stringb(downstream->output, b)) != 0) { error("%s: compose for muxclient %s", __func__, ssh_err(r)); goto out; } @@ -2687,12 +2854,14 @@ channel_proxy_upstream(Channel *c, int type, u_int32_t seq, void *ctxt) switch (type) { case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: /* record remote_id for SSH2_MSG_CHANNEL_CLOSE */ - if (cp && len > 4) + if (cp && len > 4) { c->remote_id = PEEK_U32(cp); + c->have_remote_id = 1; + } break; case SSH2_MSG_CHANNEL_CLOSE: if (c->flags & CHAN_CLOSE_SENT) - channel_free(c); + channel_free(ssh, c); else c->flags |= CHAN_CLOSE_RCVD; break; @@ -2703,257 +2872,221 @@ channel_proxy_upstream(Channel *c, int type, u_int32_t seq, void *ctxt) /* -- protocol input */ -/* ARGSUSED */ -int -channel_input_data(int type, u_int32_t seq, void *ctxt) +/* Parse a channel ID from the current packet */ +static int +channel_parse_id(struct ssh *ssh, const char *where, const char *what) { - int id; - const u_char *data; - u_int data_len, win_len; + u_int32_t id; + int r; + + if ((r = sshpkt_get_u32(ssh, &id)) != 0) { + error("%s: parse id: %s", where, ssh_err(r)); + ssh_packet_disconnect(ssh, "Invalid %s message", what); + } + if (id > INT_MAX) { + error("%s: bad channel id %u: %s", where, id, ssh_err(r)); + ssh_packet_disconnect(ssh, "Invalid %s channel id", what); + } + return (int)id; +} + +/* Lookup a channel from an ID in the current packet */ +static Channel * +channel_from_packet_id(struct ssh *ssh, const char *where, const char *what) +{ + int id = channel_parse_id(ssh, where, what); Channel *c; - /* Get the channel number and verify it. */ - id = packet_get_int(); - c = channel_lookup(id); - if (c == NULL) - packet_disconnect("Received data for nonexistent channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + if ((c = channel_lookup(ssh, id)) == NULL) { + ssh_packet_disconnect(ssh, + "%s packet referred to nonexistent channel %d", what, id); + } + return c; +} + +int +channel_input_data(int type, u_int32_t seq, struct ssh *ssh) +{ + const u_char *data; + size_t data_len, win_len; + Channel *c = channel_from_packet_id(ssh, __func__, "data"); + int r; + + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; /* Ignore any data for non-open channels (might happen on close) */ if (c->type != SSH_CHANNEL_OPEN && + c->type != SSH_CHANNEL_RDYNAMIC_OPEN && + c->type != SSH_CHANNEL_RDYNAMIC_FINISH && c->type != SSH_CHANNEL_X11_OPEN) return 0; /* Get the data. */ - data = packet_get_string_ptr(&data_len); + if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0) + fatal("%s: channel %d: get data: %s", __func__, + c->self, ssh_err(r)); + ssh_packet_check_eom(ssh); + win_len = data_len; if (c->datagram) win_len += 4; /* string length header */ /* - * Ignore data for protocol > 1.3 if output end is no longer open. - * For protocol 2 the sending side is reducing its window as it sends - * data, so we must 'fake' consumption of the data in order to ensure - * that window updates are sent back. Otherwise the connection might - * deadlock. + * The sending side reduces its window as it sends data, so we + * must 'fake' consumption of the data in order to ensure that window + * updates are sent back. Otherwise the connection might deadlock. */ - if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN) { - if (compat20) { - c->local_window -= win_len; - c->local_consumed += win_len; - } + if (c->ostate != CHAN_OUTPUT_OPEN) { + c->local_window -= win_len; + c->local_consumed += win_len; return 0; } - if (compat20) { - if (win_len > c->local_maxpacket) { - logit("channel %d: rcvd big packet %d, maxpack %d", - c->self, win_len, c->local_maxpacket); - } - if (win_len > c->local_window) { - logit("channel %d: rcvd too much data %d, win %d", - c->self, win_len, c->local_window); - return 0; - } - c->local_window -= win_len; + if (win_len > c->local_maxpacket) { + logit("channel %d: rcvd big packet %zu, maxpack %u", + c->self, win_len, c->local_maxpacket); + return 0; } - if (c->datagram) - buffer_put_string(&c->output, data, data_len); - else - buffer_append(&c->output, data, data_len); - packet_check_eom(); + if (win_len > c->local_window) { + logit("channel %d: rcvd too much data %zu, win %u", + c->self, win_len, c->local_window); + return 0; + } + c->local_window -= win_len; + + if (c->datagram) { + if ((r = sshbuf_put_string(c->output, data, data_len)) != 0) + fatal("%s: channel %d: append datagram: %s", + __func__, c->self, ssh_err(r)); + } else if ((r = sshbuf_put(c->output, data, data_len)) != 0) + fatal("%s: channel %d: append data: %s", + __func__, c->self, ssh_err(r)); + return 0; } -/* ARGSUSED */ int -channel_input_extended_data(int type, u_int32_t seq, void *ctxt) +channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh) { - int id; - char *data; - u_int data_len, tcode; - Channel *c; + const u_char *data; + size_t data_len; + u_int32_t tcode; + Channel *c = channel_from_packet_id(ssh, __func__, "extended data"); + int r; - /* Get the channel number and verify it. */ - id = packet_get_int(); - c = channel_lookup(id); - - if (c == NULL) - packet_disconnect("Received extended_data for bad channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (c->type != SSH_CHANNEL_OPEN) { - logit("channel %d: ext data for non open", id); + logit("channel %d: ext data for non open", c->self); return 0; } if (c->flags & CHAN_EOF_RCVD) { if (datafellows & SSH_BUG_EXTEOF) - debug("channel %d: accepting ext data after eof", id); + debug("channel %d: accepting ext data after eof", + c->self); else - packet_disconnect("Received extended_data after EOF " - "on channel %d.", id); + ssh_packet_disconnect(ssh, "Received extended_data " + "after EOF on channel %d.", c->self); + } + + if ((r = sshpkt_get_u32(ssh, &tcode)) != 0) { + error("%s: parse tcode: %s", __func__, ssh_err(r)); + ssh_packet_disconnect(ssh, "Invalid extended_data message"); } - tcode = packet_get_int(); if (c->efd == -1 || c->extended_usage != CHAN_EXTENDED_WRITE || tcode != SSH2_EXTENDED_DATA_STDERR) { logit("channel %d: bad ext data", c->self); return 0; } - data = packet_get_string(&data_len); - packet_check_eom(); + if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0) { + error("%s: parse data: %s", __func__, ssh_err(r)); + ssh_packet_disconnect(ssh, "Invalid extended_data message"); + } + ssh_packet_check_eom(ssh); + if (data_len > c->local_window) { - logit("channel %d: rcvd too much extended_data %d, win %d", + logit("channel %d: rcvd too much extended_data %zu, win %u", c->self, data_len, c->local_window); - free(data); return 0; } - debug2("channel %d: rcvd ext data %d", c->self, data_len); + debug2("channel %d: rcvd ext data %zu", c->self, data_len); + /* XXX sshpkt_getb? */ + if ((r = sshbuf_put(c->extended, data, data_len)) != 0) + error("%s: append: %s", __func__, ssh_err(r)); c->local_window -= data_len; - buffer_append(&c->extended, data, data_len); - free(data); return 0; } -/* ARGSUSED */ int -channel_input_ieof(int type, u_int32_t seq, void *ctxt) +channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh) { - int id; - Channel *c; + Channel *c = channel_from_packet_id(ssh, __func__, "ieof"); - id = packet_get_int(); - packet_check_eom(); - c = channel_lookup(id); - if (c == NULL) - packet_disconnect("Received ieof for nonexistent channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + ssh_packet_check_eom(ssh); + + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; - chan_rcvd_ieof(c); + chan_rcvd_ieof(ssh, c); /* XXX force input close */ if (c->force_drain && c->istate == CHAN_INPUT_OPEN) { debug("channel %d: FORCE input drain", c->self); c->istate = CHAN_INPUT_WAIT_DRAIN; - if (buffer_len(&c->input) == 0) - chan_ibuf_empty(c); + if (sshbuf_len(c->input) == 0) + chan_ibuf_empty(ssh, c); } return 0; } -/* ARGSUSED */ int -channel_input_close(int type, u_int32_t seq, void *ctxt) +channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh) { - int id; - Channel *c; + Channel *c = channel_from_packet_id(ssh, __func__, "oclose"); - id = packet_get_int(); - packet_check_eom(); - c = channel_lookup(id); - if (c == NULL) - packet_disconnect("Received close for nonexistent channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; - /* - * Send a confirmation that we have closed the channel and no more - * data is coming for it. - */ - packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION); - packet_put_int(c->remote_id); - packet_send(); - - /* - * If the channel is in closed state, we have sent a close request, - * and the other side will eventually respond with a confirmation. - * Thus, we cannot free the channel here, because then there would be - * no-one to receive the confirmation. The channel gets freed when - * the confirmation arrives. - */ - if (c->type != SSH_CHANNEL_CLOSED) { - /* - * Not a closed channel - mark it as draining, which will - * cause it to be freed later. - */ - buffer_clear(&c->input); - c->type = SSH_CHANNEL_OUTPUT_DRAINING; - } + ssh_packet_check_eom(ssh); + chan_rcvd_oclose(ssh, c); return 0; } -/* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */ -/* ARGSUSED */ int -channel_input_oclose(int type, u_int32_t seq, void *ctxt) +channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh) { - int id = packet_get_int(); - Channel *c = channel_lookup(id); + Channel *c = channel_from_packet_id(ssh, __func__, "open confirmation"); + u_int32_t remote_window, remote_maxpacket; + int r; - if (c == NULL) - packet_disconnect("Received oclose for nonexistent channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) - return 0; - packet_check_eom(); - chan_rcvd_oclose(c); - return 0; -} - -/* ARGSUSED */ -int -channel_input_close_confirmation(int type, u_int32_t seq, void *ctxt) -{ - int id = packet_get_int(); - Channel *c = channel_lookup(id); - - if (c == NULL) - packet_disconnect("Received close confirmation for " - "out-of-range channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) - return 0; - packet_check_eom(); - if (c->type != SSH_CHANNEL_CLOSED && c->type != SSH_CHANNEL_ABANDONED) - packet_disconnect("Received close confirmation for " - "non-closed channel %d (type %d).", id, c->type); - channel_free(c); - return 0; -} - -/* ARGSUSED */ -int -channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt) -{ - int id, remote_id; - Channel *c; - - id = packet_get_int(); - c = channel_lookup(id); - - if (c==NULL) - packet_disconnect("Received open confirmation for " - "unknown channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (c->type != SSH_CHANNEL_OPENING) packet_disconnect("Received open confirmation for " - "non-opening channel %d.", id); - remote_id = packet_get_int(); - /* Record the remote channel number and mark that the channel is now open. */ - c->remote_id = remote_id; - c->type = SSH_CHANNEL_OPEN; - - if (compat20) { - c->remote_window = packet_get_int(); - c->remote_maxpacket = packet_get_int(); - if (c->open_confirm) { - debug2("callback start"); - c->open_confirm(c->self, 1, c->open_confirm_ctx); - debug2("callback done"); - } - debug2("channel %d: open confirm rwindow %u rmax %u", c->self, - c->remote_window, c->remote_maxpacket); + "non-opening channel %d.", c->self); + /* + * Record the remote channel number and mark that the channel + * is now open. + */ + if ((r = sshpkt_get_u32(ssh, &c->remote_id)) != 0 || + (r = sshpkt_get_u32(ssh, &remote_window)) != 0 || + (r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0) { + error("%s: window/maxpacket: %s", __func__, ssh_err(r)); + packet_disconnect("Invalid open confirmation message"); } - packet_check_eom(); + ssh_packet_check_eom(ssh); + + c->have_remote_id = 1; + c->remote_window = remote_window; + c->remote_maxpacket = remote_maxpacket; + c->type = SSH_CHANNEL_OPEN; + if (c->open_confirm) { + debug2("%s: channel %d: callback start", __func__, c->self); + c->open_confirm(ssh, c->self, 1, c->open_confirm_ctx); + debug2("%s: channel %d: callback done", __func__, c->self); + } + debug2("channel %d: open confirm rwindow %u rmax %u", c->self, + c->remote_window, c->remote_maxpacket); return 0; } @@ -2973,134 +3106,97 @@ reason2txt(int reason) return "unknown reason"; } -/* ARGSUSED */ int -channel_input_open_failure(int type, u_int32_t seq, void *ctxt) +channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh) { - int id, reason; - char *msg = NULL, *lang = NULL; - Channel *c; + Channel *c = channel_from_packet_id(ssh, __func__, "open failure"); + u_int32_t reason; + char *msg = NULL; + int r; - id = packet_get_int(); - c = channel_lookup(id); - - if (c==NULL) - packet_disconnect("Received open failure for " - "unknown channel %d.", id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (c->type != SSH_CHANNEL_OPENING) packet_disconnect("Received open failure for " - "non-opening channel %d.", id); - if (compat20) { - reason = packet_get_int(); - if (!(datafellows & SSH_BUG_OPENFAILURE)) { - msg = packet_get_string(NULL); - lang = packet_get_string(NULL); - } - logit("channel %d: open failed: %s%s%s", id, - reason2txt(reason), msg ? ": ": "", msg ? msg : ""); - free(msg); - free(lang); - if (c->open_confirm) { - debug2("callback start"); - c->open_confirm(c->self, 0, c->open_confirm_ctx); - debug2("callback done"); + "non-opening channel %d.", c->self); + if ((r = sshpkt_get_u32(ssh, &reason)) != 0) { + error("%s: reason: %s", __func__, ssh_err(r)); + packet_disconnect("Invalid open failure message"); + } + if ((datafellows & SSH_BUG_OPENFAILURE) == 0) { + /* skip language */ + if ((r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 || + (r = sshpkt_get_string_direct(ssh, NULL, NULL)) != 0) { + error("%s: message/lang: %s", __func__, ssh_err(r)); + packet_disconnect("Invalid open failure message"); } } - packet_check_eom(); + ssh_packet_check_eom(ssh); + logit("channel %d: open failed: %s%s%s", c->self, + reason2txt(reason), msg ? ": ": "", msg ? msg : ""); + free(msg); + if (c->open_confirm) { + debug2("%s: channel %d: callback start", __func__, c->self); + c->open_confirm(ssh, c->self, 0, c->open_confirm_ctx); + debug2("%s: channel %d: callback done", __func__, c->self); + } /* Schedule the channel for cleanup/deletion. */ - chan_mark_dead(c); + chan_mark_dead(ssh, c); return 0; } -/* ARGSUSED */ int -channel_input_window_adjust(int type, u_int32_t seq, void *ctxt) +channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh) { + int id = channel_parse_id(ssh, __func__, "window adjust"); Channel *c; - int id; - u_int adjust, tmp; + u_int32_t adjust; + u_int new_rwin; + int r; - if (!compat20) - return 0; - - /* Get the channel number and verify it. */ - id = packet_get_int(); - c = channel_lookup(id); - - if (c == NULL) { + if ((c = channel_lookup(ssh, id)) == NULL) { logit("Received window adjust for non-open channel %d.", id); return 0; } - if (channel_proxy_upstream(c, type, seq, ctxt)) + + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; - adjust = packet_get_int(); - packet_check_eom(); - debug2("channel %d: rcvd adjust %u", id, adjust); - if ((tmp = c->remote_window + adjust) < c->remote_window) - fatal("channel %d: adjust %u overflows remote window %u", - id, adjust, c->remote_window); - c->remote_window = tmp; - return 0; -} - -/* ARGSUSED */ -int -channel_input_port_open(int type, u_int32_t seq, void *ctxt) -{ - Channel *c = NULL; - u_short host_port; - char *host, *originator_string; - int remote_id; - - remote_id = packet_get_int(); - host = packet_get_string(NULL); - host_port = packet_get_int(); - - if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) { - originator_string = packet_get_string(NULL); - } else { - originator_string = xstrdup("unknown (remote did not supply name)"); + if ((r = sshpkt_get_u32(ssh, &adjust)) != 0) { + error("%s: adjust: %s", __func__, ssh_err(r)); + packet_disconnect("Invalid window adjust message"); } - packet_check_eom(); - c = channel_connect_to_port(host, host_port, - "connected socket", originator_string, NULL, NULL); - free(originator_string); - free(host); - if (c == NULL) { - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(remote_id); - packet_send(); - } else - c->remote_id = remote_id; + ssh_packet_check_eom(ssh); + debug2("channel %d: rcvd adjust %u", c->self, adjust); + if ((new_rwin = c->remote_window + adjust) < c->remote_window) { + fatal("channel %d: adjust %u overflows remote window %u", + c->self, adjust, c->remote_window); + } + c->remote_window = new_rwin; return 0; } -/* ARGSUSED */ int -channel_input_status_confirm(int type, u_int32_t seq, void *ctxt) +channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh) { + int id = channel_parse_id(ssh, __func__, "status confirm"); Channel *c; struct channel_confirm *cc; - int id; /* Reset keepalive timeout */ packet_set_alive_timeouts(0); - id = packet_get_int(); - debug2("channel_input_status_confirm: type %d id %d", type, id); + debug2("%s: type %d id %d", __func__, type, id); - if ((c = channel_lookup(id)) == NULL) { - logit("channel_input_status_confirm: %d: unknown", id); + if ((c = channel_lookup(ssh, id)) == NULL) { + logit("%s: %d: unknown", __func__, id); return 0; - } - if (channel_proxy_upstream(c, type, seq, ctxt)) + } + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; - packet_check_eom(); + ssh_packet_check_eom(ssh); if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL) return 0; - cc->cb(type, c, cc->ctx); + cc->cb(ssh, type, c, cc->ctx); TAILQ_REMOVE(&c->status_confirms, cc, entry); explicit_bzero(cc, sizeof(*cc)); free(cc); @@ -3110,9 +3206,9 @@ channel_input_status_confirm(int type, u_int32_t seq, void *ctxt) /* -- tcp forwarding */ void -channel_set_af(int af) +channel_set_af(struct ssh *ssh, int af) { - IPv4or6 = af; + ssh->chanctxt->IPv4or6 = af; } @@ -3180,8 +3276,9 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, } static int -channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, - int *allocated_listen_port, struct ForwardOptions *fwd_opts) +channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type, + struct Forward *fwd, int *allocated_listen_port, + struct ForwardOptions *fwd_opts) { Channel *c; int sock, r, success = 0, wildcard = 0, is_client; @@ -3218,7 +3315,7 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, * set to NULL and hints.ai_flags is not AI_PASSIVE */ memset(&hints, 0, sizeof(hints)); - hints.ai_family = IPv4or6; + hints.ai_family = ssh->chanctxt->IPv4or6; hints.ai_flags = wildcard ? AI_PASSIVE : 0; hints.ai_socktype = SOCK_STREAM; snprintf(strport, sizeof strport, "%d", fwd->listen_port); @@ -3252,12 +3349,14 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, * If allocating a port for -R forwards, then use the * same port for all address families. */ - if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 && - allocated_listen_port != NULL && *allocated_listen_port > 0) + if (type == SSH_CHANNEL_RPORT_LISTENER && + fwd->listen_port == 0 && allocated_listen_port != NULL && + *allocated_listen_port > 0) *lport_p = htons(*allocated_listen_port); if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), - strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { + strport, sizeof(strport), + NI_NUMERICHOST|NI_NUMERICSERV) != 0) { error("%s: getnameinfo failed", __func__); continue; } @@ -3278,7 +3377,10 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, /* Bind the socket to the address. */ if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { - /* address can be in use ipv6 address is already bound */ + /* + * address can be in if use ipv6 address is + * already bound + */ if (!ai->ai_next) error("bind: %.100s", strerror(errno)); else @@ -3298,7 +3400,8 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, * fwd->listen_port == 0 requests a dynamically allocated port - * record what we got. */ - if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 && + if (type == SSH_CHANNEL_RPORT_LISTENER && + fwd->listen_port == 0 && allocated_listen_port != NULL && *allocated_listen_port == 0) { *allocated_listen_port = get_local_port(sock); @@ -3307,7 +3410,7 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, } /* Allocate a channel number for the socket. */ - c = channel_new("port listener", type, sock, sock, -1, + c = channel_new(ssh, "port listener", type, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "port listener", 1); c->path = xstrdup(host); @@ -3328,8 +3431,8 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, } static int -channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd, - struct ForwardOptions *fwd_opts) +channel_setup_fwd_listener_streamlocal(struct ssh *ssh, int type, + struct Forward *fwd, struct ForwardOptions *fwd_opts) { struct sockaddr_un sunaddr; const char *path; @@ -3391,7 +3494,7 @@ channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd, debug("Local forwarding listening on path %s.", fwd->listen_path); /* Allocate a channel number for the socket. */ - c = channel_new("unix listener", type, sock, sock, -1, + c = channel_new(ssh, "unix listener", type, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "unix listener", 1); c->path = xstrdup(path); @@ -3402,66 +3505,71 @@ channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd, } static int -channel_cancel_rport_listener_tcpip(const char *host, u_short port) +channel_cancel_rport_listener_tcpip(struct ssh *ssh, + const char *host, u_short port) { u_int i; int found = 0; - for (i = 0; i < channels_alloc; i++) { - Channel *c = channels[i]; + for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { + Channel *c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_RPORT_LISTENER) continue; if (strcmp(c->path, host) == 0 && c->listening_port == port) { debug2("%s: close channel %d", __func__, i); - channel_free(c); + channel_free(ssh, c); found = 1; } } - return (found); + return found; } static int -channel_cancel_rport_listener_streamlocal(const char *path) +channel_cancel_rport_listener_streamlocal(struct ssh *ssh, const char *path) { u_int i; int found = 0; - for (i = 0; i < channels_alloc; i++) { - Channel *c = channels[i]; + for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { + Channel *c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER) continue; if (c->path == NULL) continue; if (strcmp(c->path, path) == 0) { debug2("%s: close channel %d", __func__, i); - channel_free(c); + channel_free(ssh, c); found = 1; } } - return (found); + return found; } int -channel_cancel_rport_listener(struct Forward *fwd) +channel_cancel_rport_listener(struct ssh *ssh, struct Forward *fwd) { - if (fwd->listen_path != NULL) - return channel_cancel_rport_listener_streamlocal(fwd->listen_path); - else - return channel_cancel_rport_listener_tcpip(fwd->listen_host, fwd->listen_port); + if (fwd->listen_path != NULL) { + return channel_cancel_rport_listener_streamlocal(ssh, + fwd->listen_path); + } else { + return channel_cancel_rport_listener_tcpip(ssh, + fwd->listen_host, fwd->listen_port); + } } static int -channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport, - int cport, struct ForwardOptions *fwd_opts) +channel_cancel_lport_listener_tcpip(struct ssh *ssh, + const char *lhost, u_short lport, int cport, + struct ForwardOptions *fwd_opts) { u_int i; int found = 0; const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts); - for (i = 0; i < channels_alloc; i++) { - Channel *c = channels[i]; + for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { + Channel *c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_PORT_LISTENER) continue; if (c->listening_port != lport) @@ -3479,16 +3587,16 @@ channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport, continue; if (addr == NULL || strcmp(c->listening_addr, addr) == 0) { debug2("%s: close channel %d", __func__, i); - channel_free(c); + channel_free(ssh, c); found = 1; } } - return (found); + return found; } static int -channel_cancel_lport_listener_streamlocal(const char *path) +channel_cancel_lport_listener_streamlocal(struct ssh *ssh, const char *path) { u_int i; int found = 0; @@ -3498,54 +3606,59 @@ channel_cancel_lport_listener_streamlocal(const char *path) return 0; } - for (i = 0; i < channels_alloc; i++) { - Channel *c = channels[i]; + for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { + Channel *c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER) continue; if (c->listening_addr == NULL) continue; if (strcmp(c->listening_addr, path) == 0) { debug2("%s: close channel %d", __func__, i); - channel_free(c); + channel_free(ssh, c); found = 1; } } - return (found); + return found; } int -channel_cancel_lport_listener(struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts) -{ - if (fwd->listen_path != NULL) - return channel_cancel_lport_listener_streamlocal(fwd->listen_path); - else - return channel_cancel_lport_listener_tcpip(fwd->listen_host, fwd->listen_port, cport, fwd_opts); -} - -/* protocol local port fwd, used by ssh (and sshd in v1) */ -int -channel_setup_local_fwd_listener(struct Forward *fwd, struct ForwardOptions *fwd_opts) +channel_cancel_lport_listener(struct ssh *ssh, + struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts) { if (fwd->listen_path != NULL) { - return channel_setup_fwd_listener_streamlocal( + return channel_cancel_lport_listener_streamlocal(ssh, + fwd->listen_path); + } else { + return channel_cancel_lport_listener_tcpip(ssh, + fwd->listen_host, fwd->listen_port, cport, fwd_opts); + } +} + +/* protocol local port fwd, used by ssh */ +int +channel_setup_local_fwd_listener(struct ssh *ssh, + struct Forward *fwd, struct ForwardOptions *fwd_opts) +{ + if (fwd->listen_path != NULL) { + return channel_setup_fwd_listener_streamlocal(ssh, SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts); } else { - return channel_setup_fwd_listener_tcpip(SSH_CHANNEL_PORT_LISTENER, - fwd, NULL, fwd_opts); + return channel_setup_fwd_listener_tcpip(ssh, + SSH_CHANNEL_PORT_LISTENER, fwd, NULL, fwd_opts); } } /* protocol v2 remote port fwd, used by sshd */ int -channel_setup_remote_fwd_listener(struct Forward *fwd, +channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd, int *allocated_listen_port, struct ForwardOptions *fwd_opts) { if (fwd->listen_path != NULL) { - return channel_setup_fwd_listener_streamlocal( + return channel_setup_fwd_listener_streamlocal(ssh, SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts); } else { - return channel_setup_fwd_listener_tcpip( + return channel_setup_fwd_listener_tcpip(ssh, SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port, fwd_opts); } @@ -3579,81 +3692,61 @@ channel_rfwd_bind_host(const char *listen_host) * channel_update_permitted_opens(). */ int -channel_request_remote_forwarding(struct Forward *fwd) +channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) { - int type, success = 0, idx = -1; + int r, success = 0, idx = -1; + char *host_to_connect, *listen_host, *listen_path; + int port_to_connect, listen_port; /* Send the forward request to the remote side. */ - if (compat20) { - packet_start(SSH2_MSG_GLOBAL_REQUEST); - if (fwd->listen_path != NULL) { - packet_put_cstring("streamlocal-forward@openssh.com"); - packet_put_char(1); /* boolean: want reply */ - packet_put_cstring(fwd->listen_path); - } else { - packet_put_cstring("tcpip-forward"); - packet_put_char(1); /* boolean: want reply */ - packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host)); - packet_put_int(fwd->listen_port); - } - packet_send(); - packet_write_wait(); - /* Assume that server accepts the request */ - success = 1; - } else if (fwd->listen_path == NULL) { - packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); - packet_put_int(fwd->listen_port); - packet_put_cstring(fwd->connect_host); - packet_put_int(fwd->connect_port); - packet_send(); - packet_write_wait(); - - /* Wait for response from the remote side. */ - type = packet_read(); - switch (type) { - case SSH_SMSG_SUCCESS: - success = 1; - break; - case SSH_SMSG_FAILURE: - break; - default: - /* Unknown packet */ - packet_disconnect("Protocol error for port forward request:" - "received packet type %d.", type); - } + if (fwd->listen_path != NULL) { + if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || + (r = sshpkt_put_cstring(ssh, + "streamlocal-forward@openssh.com")) != 0 || + (r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */ + (r = sshpkt_put_cstring(ssh, fwd->listen_path)) != 0 || + (r = sshpkt_send(ssh)) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) + fatal("%s: request streamlocal: %s", + __func__, ssh_err(r)); } else { - logit("Warning: Server does not support remote stream local forwarding."); + if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || + (r = sshpkt_put_cstring(ssh, "tcpip-forward")) != 0 || + (r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */ + (r = sshpkt_put_cstring(ssh, + channel_rfwd_bind_host(fwd->listen_host))) != 0 || + (r = sshpkt_put_u32(ssh, fwd->listen_port)) != 0 || + (r = sshpkt_send(ssh)) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) + fatal("%s: request tcpip-forward: %s", + __func__, ssh_err(r)); } + /* Assume that server accepts the request */ + success = 1; if (success) { /* Record that connection to this host/port is permitted. */ - permitted_opens = xreallocarray(permitted_opens, - num_permitted_opens + 1, sizeof(*permitted_opens)); - idx = num_permitted_opens++; + host_to_connect = listen_host = listen_path = NULL; + port_to_connect = listen_port = 0; if (fwd->connect_path != NULL) { - permitted_opens[idx].host_to_connect = - xstrdup(fwd->connect_path); - permitted_opens[idx].port_to_connect = - PORT_STREAMLOCAL; + host_to_connect = xstrdup(fwd->connect_path); + port_to_connect = PORT_STREAMLOCAL; } else { - permitted_opens[idx].host_to_connect = - xstrdup(fwd->connect_host); - permitted_opens[idx].port_to_connect = - fwd->connect_port; + host_to_connect = xstrdup(fwd->connect_host); + port_to_connect = fwd->connect_port; } if (fwd->listen_path != NULL) { - permitted_opens[idx].listen_host = NULL; - permitted_opens[idx].listen_path = - xstrdup(fwd->listen_path); - permitted_opens[idx].listen_port = PORT_STREAMLOCAL; + listen_path = xstrdup(fwd->listen_path); + listen_port = PORT_STREAMLOCAL; } else { - permitted_opens[idx].listen_host = - fwd->listen_host ? xstrdup(fwd->listen_host) : NULL; - permitted_opens[idx].listen_path = NULL; - permitted_opens[idx].listen_port = fwd->listen_port; + if (fwd->listen_host != NULL) + listen_host = xstrdup(fwd->listen_host); + listen_port = fwd->listen_port; } - permitted_opens[idx].downstream = NULL; + idx = fwd_perm_list_add(ssh, FWDPERM_USER, + host_to_connect, port_to_connect, + listen_host, listen_path, listen_port, NULL); } - return (idx); + return idx; } static int @@ -3718,36 +3811,33 @@ open_listen_match_streamlocal(ForwardPermission *allowed_open, * local side. */ static int -channel_request_rforward_cancel_tcpip(const char *host, u_short port) +channel_request_rforward_cancel_tcpip(struct ssh *ssh, + const char *host, u_short port) { - int i; + struct ssh_channels *sc = ssh->chanctxt; + int r; + u_int i; + ForwardPermission *fp; - if (!compat20) - return -1; - - for (i = 0; i < num_permitted_opens; i++) { - if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0)) + for (i = 0; i < sc->num_permitted_opens; i++) { + fp = &sc->permitted_opens[i]; + if (open_listen_match_tcpip(fp, host, port, 0)) break; + fp = NULL; } - if (i >= num_permitted_opens) { + if (fp == NULL) { debug("%s: requested forward not found", __func__); return -1; } - packet_start(SSH2_MSG_GLOBAL_REQUEST); - packet_put_cstring("cancel-tcpip-forward"); - packet_put_char(0); - packet_put_cstring(channel_rfwd_bind_host(host)); - packet_put_int(port); - packet_send(); + if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || + (r = sshpkt_put_cstring(ssh, "cancel-tcpip-forward")) != 0 || + (r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */ + (r = sshpkt_put_cstring(ssh, channel_rfwd_bind_host(host))) != 0 || + (r = sshpkt_put_u32(ssh, port)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("%s: send cancel: %s", __func__, ssh_err(r)); - permitted_opens[i].listen_port = 0; - permitted_opens[i].port_to_connect = 0; - free(permitted_opens[i].host_to_connect); - permitted_opens[i].host_to_connect = NULL; - free(permitted_opens[i].listen_host); - permitted_opens[i].listen_host = NULL; - permitted_opens[i].listen_path = NULL; - permitted_opens[i].downstream = NULL; + fwd_perm_clear(fp); /* unregister */ return 0; } @@ -3757,35 +3847,32 @@ channel_request_rforward_cancel_tcpip(const char *host, u_short port) * path from local side. */ static int -channel_request_rforward_cancel_streamlocal(const char *path) +channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path) { - int i; + struct ssh_channels *sc = ssh->chanctxt; + int r; + u_int i; + ForwardPermission *fp; - if (!compat20) - return -1; - - for (i = 0; i < num_permitted_opens; i++) { - if (open_listen_match_streamlocal(&permitted_opens[i], path)) + for (i = 0; i < sc->num_permitted_opens; i++) { + fp = &sc->permitted_opens[i]; + if (open_listen_match_streamlocal(fp, path)) break; + fp = NULL; } - if (i >= num_permitted_opens) { + if (fp == NULL) { debug("%s: requested forward not found", __func__); return -1; } - packet_start(SSH2_MSG_GLOBAL_REQUEST); - packet_put_cstring("cancel-streamlocal-forward@openssh.com"); - packet_put_char(0); - packet_put_cstring(path); - packet_send(); + if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || + (r = sshpkt_put_cstring(ssh, + "cancel-streamlocal-forward@openssh.com")) != 0 || + (r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */ + (r = sshpkt_put_cstring(ssh, path)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("%s: send cancel: %s", __func__, ssh_err(r)); - permitted_opens[i].listen_port = 0; - permitted_opens[i].port_to_connect = 0; - free(permitted_opens[i].host_to_connect); - permitted_opens[i].host_to_connect = NULL; - permitted_opens[i].listen_host = NULL; - free(permitted_opens[i].listen_path); - permitted_opens[i].listen_path = NULL; - permitted_opens[i].downstream = NULL; + fwd_perm_clear(fp); /* unregister */ return 0; } @@ -3794,14 +3881,15 @@ channel_request_rforward_cancel_streamlocal(const char *path) * Request cancellation of remote forwarding of a connection from local side. */ int -channel_request_rforward_cancel(struct Forward *fwd) +channel_request_rforward_cancel(struct ssh *ssh, struct Forward *fwd) { if (fwd->listen_path != NULL) { - return (channel_request_rforward_cancel_streamlocal( - fwd->listen_path)); + return channel_request_rforward_cancel_streamlocal(ssh, + fwd->listen_path); } else { - return (channel_request_rforward_cancel_tcpip(fwd->listen_host, - fwd->listen_port ? fwd->listen_port : fwd->allocated_port)); + return channel_request_rforward_cancel_tcpip(ssh, + fwd->listen_host, + fwd->listen_port ? fwd->listen_port : fwd->allocated_port); } } @@ -3811,28 +3899,20 @@ channel_request_rforward_cancel(struct Forward *fwd) * anyway, and the server has no way to know but to trust the client anyway. */ void -channel_permit_all_opens(void) +channel_permit_all_opens(struct ssh *ssh) { - if (num_permitted_opens == 0) - all_opens_permitted = 1; + if (ssh->chanctxt->num_permitted_opens == 0) + ssh->chanctxt->all_opens_permitted = 1; } void -channel_add_permitted_opens(char *host, int port) +channel_add_permitted_opens(struct ssh *ssh, char *host, int port) { + struct ssh_channels *sc = ssh->chanctxt; + debug("allow port forwarding to host %s port %d", host, port); - - permitted_opens = xreallocarray(permitted_opens, - num_permitted_opens + 1, sizeof(*permitted_opens)); - permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); - permitted_opens[num_permitted_opens].port_to_connect = port; - permitted_opens[num_permitted_opens].listen_host = NULL; - permitted_opens[num_permitted_opens].listen_path = NULL; - permitted_opens[num_permitted_opens].listen_port = 0; - permitted_opens[num_permitted_opens].downstream = NULL; - num_permitted_opens++; - - all_opens_permitted = 0; + fwd_perm_list_add(ssh, FWDPERM_USER, host, port, NULL, NULL, 0, NULL); + sc->all_opens_permitted = 0; } /* @@ -3841,105 +3921,61 @@ channel_add_permitted_opens(char *host, int port) * passed then they entry will be invalidated. */ void -channel_update_permitted_opens(int idx, int newport) +channel_update_permitted_opens(struct ssh *ssh, int idx, int newport) { - if (idx < 0 || idx >= num_permitted_opens) { - debug("channel_update_permitted_opens: index out of range:" - " %d num_permitted_opens %d", idx, num_permitted_opens); + struct ssh_channels *sc = ssh->chanctxt; + + if (idx < 0 || (u_int)idx >= sc->num_permitted_opens) { + debug("%s: index out of range: %d num_permitted_opens %d", + __func__, idx, sc->num_permitted_opens); return; } debug("%s allowed port %d for forwarding to host %s port %d", newport > 0 ? "Updating" : "Removing", newport, - permitted_opens[idx].host_to_connect, - permitted_opens[idx].port_to_connect); - if (newport >= 0) { - permitted_opens[idx].listen_port = + sc->permitted_opens[idx].host_to_connect, + sc->permitted_opens[idx].port_to_connect); + if (newport <= 0) + fwd_perm_clear(&sc->permitted_opens[idx]); + else { + sc->permitted_opens[idx].listen_port = (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport; - } else { - permitted_opens[idx].listen_port = 0; - permitted_opens[idx].port_to_connect = 0; - free(permitted_opens[idx].host_to_connect); - permitted_opens[idx].host_to_connect = NULL; - free(permitted_opens[idx].listen_host); - permitted_opens[idx].listen_host = NULL; - free(permitted_opens[idx].listen_path); - permitted_opens[idx].listen_path = NULL; } } int -channel_add_adm_permitted_opens(char *host, int port) +channel_add_adm_permitted_opens(struct ssh *ssh, char *host, int port) { debug("config allows port forwarding to host %s port %d", host, port); - - permitted_adm_opens = xreallocarray(permitted_adm_opens, - num_adm_permitted_opens + 1, sizeof(*permitted_adm_opens)); - permitted_adm_opens[num_adm_permitted_opens].host_to_connect - = xstrdup(host); - permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port; - permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL; - permitted_adm_opens[num_adm_permitted_opens].listen_path = NULL; - permitted_adm_opens[num_adm_permitted_opens].listen_port = 0; - return ++num_adm_permitted_opens; + return fwd_perm_list_add(ssh, FWDPERM_ADMIN, host, port, + NULL, NULL, 0, NULL); } void -channel_disable_adm_local_opens(void) +channel_disable_adm_local_opens(struct ssh *ssh) { - channel_clear_adm_permitted_opens(); - permitted_adm_opens = xcalloc(sizeof(*permitted_adm_opens), 1); - permitted_adm_opens[num_adm_permitted_opens].host_to_connect = NULL; - num_adm_permitted_opens = 1; + channel_clear_adm_permitted_opens(ssh); + fwd_perm_list_add(ssh, FWDPERM_ADMIN, NULL, 0, NULL, NULL, 0, NULL); } void -channel_clear_permitted_opens(void) +channel_clear_permitted_opens(struct ssh *ssh) { - int i; + struct ssh_channels *sc = ssh->chanctxt; - for (i = 0; i < num_permitted_opens; i++) { - free(permitted_opens[i].host_to_connect); - free(permitted_opens[i].listen_host); - free(permitted_opens[i].listen_path); - } - free(permitted_opens); - permitted_opens = NULL; - num_permitted_opens = 0; + sc->permitted_opens = xrecallocarray(sc->permitted_opens, + sc->num_permitted_opens, 0, sizeof(*sc->permitted_opens)); + sc->num_permitted_opens = 0; } void -channel_clear_adm_permitted_opens(void) +channel_clear_adm_permitted_opens(struct ssh *ssh) { - int i; + struct ssh_channels *sc = ssh->chanctxt; - for (i = 0; i < num_adm_permitted_opens; i++) { - free(permitted_adm_opens[i].host_to_connect); - free(permitted_adm_opens[i].listen_host); - free(permitted_adm_opens[i].listen_path); - } - free(permitted_adm_opens); - permitted_adm_opens = NULL; - num_adm_permitted_opens = 0; -} - -void -channel_print_adm_permitted_opens(void) -{ - int i; - - printf("permitopen"); - if (num_adm_permitted_opens == 0) { - printf(" any\n"); - return; - } - for (i = 0; i < num_adm_permitted_opens; i++) - if (permitted_adm_opens[i].host_to_connect == NULL) - printf(" none"); - else - printf(" %s:%d", permitted_adm_opens[i].host_to_connect, - permitted_adm_opens[i].port_to_connect); - printf("\n"); + sc->permitted_adm_opens = xrecallocarray(sc->permitted_adm_opens, + sc->num_adm_permitted_opens, 0, sizeof(*sc->permitted_adm_opens)); + sc->num_adm_permitted_opens = 0; } /* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */ @@ -3961,7 +3997,8 @@ connect_next(struct channel_connect *cctx) { int sock, saved_errno; struct sockaddr_un *sunaddr; - char ntop[NI_MAXHOST], strport[MAXIMUM(NI_MAXSERV,sizeof(sunaddr->sun_path))]; + char ntop[NI_MAXHOST]; + char strport[MAXIMUM(NI_MAXSERV, sizeof(sunaddr->sun_path))]; for (; cctx->ai; cctx->ai = cctx->ai->ai_next) { switch (cctx->ai->ai_family) { @@ -4027,21 +4064,18 @@ channel_connect_ctx_free(struct channel_connect *cctx) } /* - * Return CONNECTING channel to remote host:port or local socket path, + * Return connecting socket to remote host:port or local socket path, * passing back the failure reason if appropriate. */ -static Channel * -connect_to_reason(const char *name, int port, char *ctype, char *rname, - int *reason, const char **errmsg) +static int +connect_to_helper(struct ssh *ssh, const char *name, int port, int socktype, + char *ctype, char *rname, struct channel_connect *cctx, + int *reason, const char **errmsg) { struct addrinfo hints; int gaierr; int sock = -1; char strport[NI_MAXSERV]; - struct channel_connect cctx; - Channel *c; - - memset(&cctx, 0, sizeof(cctx)); if (port == PORT_STREAMLOCAL) { struct sockaddr_un *sunaddr; @@ -4049,7 +4083,7 @@ connect_to_reason(const char *name, int port, char *ctype, char *rname, if (strlen(name) > sizeof(sunaddr->sun_path)) { error("%.100s: %.100s", name, strerror(ENAMETOOLONG)); - return (NULL); + return -1; } /* @@ -4062,18 +4096,18 @@ connect_to_reason(const char *name, int port, char *ctype, char *rname, ai->ai_addr = (struct sockaddr *)(ai + 1); ai->ai_addrlen = sizeof(*sunaddr); ai->ai_family = AF_UNIX; - ai->ai_socktype = SOCK_STREAM; + ai->ai_socktype = socktype; ai->ai_protocol = PF_UNSPEC; sunaddr = (struct sockaddr_un *)ai->ai_addr; sunaddr->sun_family = AF_UNIX; strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path)); - cctx.aitop = ai; + cctx->aitop = ai; } else { memset(&hints, 0, sizeof(hints)); - hints.ai_family = IPv4or6; - hints.ai_socktype = SOCK_STREAM; + hints.ai_family = ssh->chanctxt->IPv4or6; + hints.ai_socktype = socktype; snprintf(strport, sizeof strport, "%d", port); - if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) + if ((gaierr = getaddrinfo(name, strport, &hints, &cctx->aitop)) != 0) { if (errmsg != NULL) *errmsg = ssh_gai_strerror(gaierr); @@ -4081,31 +4115,46 @@ connect_to_reason(const char *name, int port, char *ctype, char *rname, *reason = SSH2_OPEN_CONNECT_FAILED; error("connect_to %.100s: unknown host (%s)", name, ssh_gai_strerror(gaierr)); - return NULL; + return -1; } } - cctx.host = xstrdup(name); - cctx.port = port; - cctx.ai = cctx.aitop; + cctx->host = xstrdup(name); + cctx->port = port; + cctx->ai = cctx->aitop; - if ((sock = connect_next(&cctx)) == -1) { + if ((sock = connect_next(cctx)) == -1) { error("connect to %.100s port %d failed: %s", name, port, strerror(errno)); - channel_connect_ctx_free(&cctx); - return NULL; + return -1; } - c = channel_new(ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); - c->connect_ctx = cctx; - return c; + + return sock; } /* Return CONNECTING channel to remote host:port or local socket path */ static Channel * -connect_to(const char *name, int port, char *ctype, char *rname) +connect_to(struct ssh *ssh, const char *host, int port, + char *ctype, char *rname) { - return connect_to_reason(name, port, ctype, rname, NULL, NULL); + struct channel_connect cctx; + Channel *c; + int sock; + + memset(&cctx, 0, sizeof(cctx)); + sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname, + &cctx, NULL, NULL); + if (sock == -1) { + channel_connect_ctx_free(&cctx); + return NULL; + } + c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); + c->host_port = port; + c->path = xstrdup(host); + c->connect_ctx = cctx; + + return c; } /* @@ -4113,19 +4162,24 @@ connect_to(const char *name, int port, char *ctype, char *rname) * that needs to deal with this connection. */ Channel * -channel_connect_by_listen_address(const char *listen_host, +channel_connect_by_listen_address(struct ssh *ssh, const char *listen_host, u_short listen_port, char *ctype, char *rname) { - int i; + struct ssh_channels *sc = ssh->chanctxt; + u_int i; + ForwardPermission *fp; - for (i = 0; i < num_permitted_opens; i++) { - if (open_listen_match_tcpip(&permitted_opens[i], listen_host, - listen_port, 1)) { - if (permitted_opens[i].downstream) - return permitted_opens[i].downstream; - return connect_to( - permitted_opens[i].host_to_connect, - permitted_opens[i].port_to_connect, ctype, rname); + for (i = 0; i < sc->num_permitted_opens; i++) { + fp = &sc->permitted_opens[i]; + if (open_listen_match_tcpip(fp, listen_host, listen_port, 1)) { + if (fp->downstream) + return fp->downstream; + if (fp->port_to_connect == 0) + return rdynamic_connect_prepare(ssh, + ctype, rname); + return connect_to(ssh, + fp->host_to_connect, fp->port_to_connect, + ctype, rname); } } error("WARNING: Server requests forwarding for unknown listen_port %d", @@ -4134,15 +4188,19 @@ channel_connect_by_listen_address(const char *listen_host, } Channel * -channel_connect_by_listen_path(const char *path, char *ctype, char *rname) +channel_connect_by_listen_path(struct ssh *ssh, const char *path, + char *ctype, char *rname) { - int i; + struct ssh_channels *sc = ssh->chanctxt; + u_int i; + ForwardPermission *fp; - for (i = 0; i < num_permitted_opens; i++) { - if (open_listen_match_streamlocal(&permitted_opens[i], path)) { - return connect_to( - permitted_opens[i].host_to_connect, - permitted_opens[i].port_to_connect, ctype, rname); + for (i = 0; i < sc->num_permitted_opens; i++) { + fp = &sc->permitted_opens[i]; + if (open_listen_match_streamlocal(fp, path)) { + return connect_to(ssh, + fp->host_to_connect, fp->port_to_connect, + ctype, rname); } } error("WARNING: Server requests forwarding for unknown path %.100s", @@ -4152,27 +4210,36 @@ channel_connect_by_listen_path(const char *path, char *ctype, char *rname) /* Check if connecting to that port is permitted and connect. */ Channel * -channel_connect_to_port(const char *host, u_short port, char *ctype, - char *rname, int *reason, const char **errmsg) +channel_connect_to_port(struct ssh *ssh, const char *host, u_short port, + char *ctype, char *rname, int *reason, const char **errmsg) { - int i, permit, permit_adm = 1; + struct ssh_channels *sc = ssh->chanctxt; + struct channel_connect cctx; + Channel *c; + u_int i, permit, permit_adm = 1; + int sock; + ForwardPermission *fp; - permit = all_opens_permitted; + permit = sc->all_opens_permitted; if (!permit) { - for (i = 0; i < num_permitted_opens; i++) - if (open_match(&permitted_opens[i], host, port)) { + for (i = 0; i < sc->num_permitted_opens; i++) { + fp = &sc->permitted_opens[i]; + if (open_match(fp, host, port)) { permit = 1; break; } + } } - if (num_adm_permitted_opens > 0) { + if (sc->num_adm_permitted_opens > 0) { permit_adm = 0; - for (i = 0; i < num_adm_permitted_opens; i++) - if (open_match(&permitted_adm_opens[i], host, port)) { + for (i = 0; i < sc->num_adm_permitted_opens; i++) { + fp = &sc->permitted_adm_opens[i]; + if (open_match(fp, host, port)) { permit_adm = 1; break; } + } } if (!permit || !permit_adm) { @@ -4182,31 +4249,53 @@ channel_connect_to_port(const char *host, u_short port, char *ctype, *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; return NULL; } - return connect_to_reason(host, port, ctype, rname, reason, errmsg); + + memset(&cctx, 0, sizeof(cctx)); + sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname, + &cctx, reason, errmsg); + if (sock == -1) { + channel_connect_ctx_free(&cctx); + return NULL; + } + + c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); + c->host_port = port; + c->path = xstrdup(host); + c->connect_ctx = cctx; + + return c; } /* Check if connecting to that path is permitted and connect. */ Channel * -channel_connect_to_path(const char *path, char *ctype, char *rname) +channel_connect_to_path(struct ssh *ssh, const char *path, + char *ctype, char *rname) { - int i, permit, permit_adm = 1; + struct ssh_channels *sc = ssh->chanctxt; + u_int i, permit, permit_adm = 1; + ForwardPermission *fp; - permit = all_opens_permitted; + permit = sc->all_opens_permitted; if (!permit) { - for (i = 0; i < num_permitted_opens; i++) - if (open_match(&permitted_opens[i], path, PORT_STREAMLOCAL)) { + for (i = 0; i < sc->num_permitted_opens; i++) { + fp = &sc->permitted_opens[i]; + if (open_match(fp, path, PORT_STREAMLOCAL)) { permit = 1; break; } + } } - if (num_adm_permitted_opens > 0) { + if (sc->num_adm_permitted_opens > 0) { permit_adm = 0; - for (i = 0; i < num_adm_permitted_opens; i++) - if (open_match(&permitted_adm_opens[i], path, PORT_STREAMLOCAL)) { + for (i = 0; i < sc->num_adm_permitted_opens; i++) { + fp = &sc->permitted_adm_opens[i]; + if (open_match(fp, path, PORT_STREAMLOCAL)) { permit_adm = 1; break; } + } } if (!permit || !permit_adm) { @@ -4214,30 +4303,82 @@ channel_connect_to_path(const char *path, char *ctype, char *rname) "but the request was denied.", path); return NULL; } - return connect_to(path, PORT_STREAMLOCAL, ctype, rname); + return connect_to(ssh, path, PORT_STREAMLOCAL, ctype, rname); } void -channel_send_window_changes(void) +channel_send_window_changes(struct ssh *ssh) { - u_int i; + struct ssh_channels *sc = ssh->chanctxt; struct winsize ws; + int r; + u_int i; - for (i = 0; i < channels_alloc; i++) { - if (channels[i] == NULL || !channels[i]->client_tty || - channels[i]->type != SSH_CHANNEL_OPEN) + for (i = 0; i < sc->channels_alloc; i++) { + if (sc->channels[i] == NULL || !sc->channels[i]->client_tty || + sc->channels[i]->type != SSH_CHANNEL_OPEN) continue; - if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0) + if (ioctl(sc->channels[i]->rfd, TIOCGWINSZ, &ws) < 0) continue; - channel_request_start(i, "window-change", 0); - packet_put_int((u_int)ws.ws_col); - packet_put_int((u_int)ws.ws_row); - packet_put_int((u_int)ws.ws_xpixel); - packet_put_int((u_int)ws.ws_ypixel); - packet_send(); + channel_request_start(ssh, i, "window-change", 0); + if ((r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 || + (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 || + (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 || + (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("%s: channel %u: send window-change: %s", + __func__, i, ssh_err(r)); } } +/* Return RDYNAMIC_OPEN channel: channel allows SOCKS, but is not connected */ +static Channel * +rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname) +{ + Channel *c; + int r; + + c = channel_new(ssh, ctype, SSH_CHANNEL_RDYNAMIC_OPEN, -1, -1, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); + c->host_port = 0; + c->path = NULL; + + /* + * We need to open the channel before we have a FD, + * so that we can get SOCKS header from peer. + */ + if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || + (r = sshpkt_put_u32(ssh, c->self)) != 0 || + (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || + (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) { + fatal("%s: channel %i: confirm: %s", __func__, + c->self, ssh_err(r)); + } + return c; +} + +/* Return CONNECTING socket to remote host:port or local socket path */ +static int +rdynamic_connect_finish(struct ssh *ssh, Channel *c) +{ + struct channel_connect cctx; + int sock; + + memset(&cctx, 0, sizeof(cctx)); + sock = connect_to_helper(ssh, c->path, c->host_port, SOCK_STREAM, NULL, + NULL, &cctx, NULL, NULL); + if (sock == -1) + channel_connect_ctx_free(&cctx); + else { + /* similar to SSH_CHANNEL_CONNECTING but we've already sent the open */ + c->type = SSH_CHANNEL_RDYNAMIC_FINISH; + c->connect_ctx = cctx; + channel_register_fds(ssh, c, sock, sock, -1, 0, 1, 0); + } + return sock; +} + /* -- X11 forwarding */ /* @@ -4246,8 +4387,9 @@ channel_send_window_changes(void) * stored in display_numberp , or -1 if an error occurs. */ int -x11_create_display_inet(int x11_display_offset, int x11_use_localhost, - int single_connection, u_int *display_numberp, int **chanids) +x11_create_display_inet(struct ssh *ssh, int x11_display_offset, + int x11_use_localhost, int single_connection, + u_int *display_numberp, int **chanids) { Channel *nc = NULL; int display_number, sock; @@ -4264,16 +4406,18 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost, display_number++) { port = 6000 + display_number; memset(&hints, 0, sizeof(hints)); - hints.ai_family = IPv4or6; + hints.ai_family = ssh->chanctxt->IPv4or6; hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; snprintf(strport, sizeof strport, "%d", port); - if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) { + if ((gaierr = getaddrinfo(NULL, strport, + &hints, &aitop)) != 0) { error("getaddrinfo: %.100s", ssh_gai_strerror(gaierr)); return -1; } for (ai = aitop; ai; ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) + if (ai->ai_family != AF_INET && + ai->ai_family != AF_INET6) continue; sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); @@ -4297,12 +4441,11 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost, if (x11_use_localhost) channel_set_reuseaddr(sock); if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { - debug2("bind port %d: %.100s", port, strerror(errno)); + debug2("%s: bind port %d: %.100s", __func__, + port, strerror(errno)); close(sock); - - for (n = 0; n < num_socks; n++) { + for (n = 0; n < num_socks; n++) close(socks[n]); - } num_socks = 0; break; } @@ -4332,7 +4475,7 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost, *chanids = xcalloc(num_socks + 1, sizeof(**chanids)); for (n = 0; n < num_socks; n++) { sock = socks[n]; - nc = channel_new("x11 listener", + nc = channel_new(ssh, "x11 listener", SSH_CHANNEL_X11_LISTENER, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "X11 inet listener", 1); @@ -4343,7 +4486,7 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost, /* Return the display number for the DISPLAY environment variable. */ *display_numberp = display_number; - return (0); + return 0; } static int @@ -4401,7 +4544,7 @@ is_path_to_xsocket(const char *display, char *path, size_t pathlen) #endif int -x11_connect_display(void) +x11_connect_display(struct ssh *ssh) { u_int display_number; const char *display; @@ -4446,9 +4589,10 @@ x11_connect_display(void) if (strncmp(display, "unix:", 5) == 0 || display[0] == ':') { /* Connect to the unix domain socket. */ - if (sscanf(strrchr(display, ':') + 1, "%u", &display_number) != 1) { - error("Could not parse display number from DISPLAY: %.100s", - display); + if (sscanf(strrchr(display, ':') + 1, "%u", + &display_number) != 1) { + error("Could not parse display number from DISPLAY: " + "%.100s", display); return -1; } /* Create a socket. */ @@ -4470,7 +4614,10 @@ x11_connect_display(void) return -1; } *cp = 0; - /* buf now contains the host name. But first we parse the display number. */ + /* + * buf now contains the host name. But first we parse the + * display number. + */ if (sscanf(cp + 1, "%u", &display_number) != 1) { error("Could not parse display number from DISPLAY: %.100s", display); @@ -4479,7 +4626,7 @@ x11_connect_display(void) /* Look up the host address */ memset(&hints, 0, sizeof(hints)); - hints.ai_family = IPv4or6; + hints.ai_family = ssh->chanctxt->IPv4or6; hints.ai_socktype = SOCK_STREAM; snprintf(strport, sizeof strport, "%u", 6000 + display_number); if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) { @@ -4506,107 +4653,33 @@ x11_connect_display(void) } freeaddrinfo(aitop); if (!ai) { - error("connect %.100s port %u: %.100s", buf, 6000 + display_number, - strerror(errno)); + error("connect %.100s port %u: %.100s", buf, + 6000 + display_number, strerror(errno)); return -1; } set_nodelay(sock); return sock; } -/* - * This is called when SSH_SMSG_X11_OPEN is received. The packet contains - * the remote channel number. We should do whatever we want, and respond - * with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. - */ - -/* ARGSUSED */ -int -x11_input_open(int type, u_int32_t seq, void *ctxt) -{ - Channel *c = NULL; - int remote_id, sock = 0; - char *remote_host; - - debug("Received X11 open request."); - - remote_id = packet_get_int(); - - if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) { - remote_host = packet_get_string(NULL); - } else { - remote_host = xstrdup("unknown (remote did not supply name)"); - } - packet_check_eom(); - - /* Obtain a connection to the real X display. */ - sock = x11_connect_display(); - if (sock != -1) { - /* Allocate a channel for this connection. */ - c = channel_new("connected x11 socket", - SSH_CHANNEL_X11_OPEN, sock, sock, -1, 0, 0, 0, - remote_host, 1); - c->remote_id = remote_id; - c->force_drain = 1; - } - free(remote_host); - if (c == NULL) { - /* Send refusal to the remote host. */ - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(remote_id); - } else { - /* Send a confirmation to the remote host. */ - packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(remote_id); - packet_put_int(c->self); - } - packet_send(); - return 0; -} - -/* dummy protocol handler that denies SSH-1 requests (agent/x11) */ -/* ARGSUSED */ -int -deny_input_open(int type, u_int32_t seq, void *ctxt) -{ - int rchan = packet_get_int(); - - switch (type) { - case SSH_SMSG_AGENT_OPEN: - error("Warning: ssh server tried agent forwarding."); - break; - case SSH_SMSG_X11_OPEN: - error("Warning: ssh server tried X11 forwarding."); - break; - default: - error("deny_input_open: type %d", type); - break; - } - error("Warning: this is probably a break-in attempt by a malicious server."); - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(rchan); - packet_send(); - return 0; -} - /* * Requests forwarding of X11 connections, generates fake authentication * data, and enables authentication spoofing. * This should be called in the client only. */ void -x11_request_forwarding_with_spoofing(int client_session_id, const char *disp, - const char *proto, const char *data, int want_reply) +x11_request_forwarding_with_spoofing(struct ssh *ssh, int client_session_id, + const char *disp, const char *proto, const char *data, int want_reply) { + struct ssh_channels *sc = ssh->chanctxt; u_int data_len = (u_int) strlen(data) / 2; u_int i, value; - char *new_data; - int screen_number; const char *cp; + char *new_data; + int r, screen_number; - if (x11_saved_display == NULL) - x11_saved_display = xstrdup(disp); - else if (strcmp(disp, x11_saved_display) != 0) { + if (sc->x11_saved_display == NULL) + sc->x11_saved_display = xstrdup(disp); + else if (strcmp(disp, sc->x11_saved_display) != 0) { error("x11_request_forwarding_with_spoofing: different " "$DISPLAY already forwarded"); return; @@ -4620,53 +4693,37 @@ x11_request_forwarding_with_spoofing(int client_session_id, const char *disp, else screen_number = 0; - if (x11_saved_proto == NULL) { + if (sc->x11_saved_proto == NULL) { /* Save protocol name. */ - x11_saved_proto = xstrdup(proto); + sc->x11_saved_proto = xstrdup(proto); /* Extract real authentication data. */ - x11_saved_data = xmalloc(data_len); + sc->x11_saved_data = xmalloc(data_len); for (i = 0; i < data_len; i++) { if (sscanf(data + 2 * i, "%2x", &value) != 1) fatal("x11_request_forwarding: bad " "authentication data: %.100s", data); - x11_saved_data[i] = value; + sc->x11_saved_data[i] = value; } - x11_saved_data_len = data_len; + sc->x11_saved_data_len = data_len; /* Generate fake data of the same length. */ - x11_fake_data = xmalloc(data_len); - arc4random_buf(x11_fake_data, data_len); - x11_fake_data_len = data_len; + sc->x11_fake_data = xmalloc(data_len); + arc4random_buf(sc->x11_fake_data, data_len); + sc->x11_fake_data_len = data_len; } /* Convert the fake data into hex. */ - new_data = tohex(x11_fake_data, data_len); + new_data = tohex(sc->x11_fake_data, data_len); /* Send the request packet. */ - if (compat20) { - channel_request_start(client_session_id, "x11-req", want_reply); - packet_put_char(0); /* XXX bool single connection */ - } else { - packet_start(SSH_CMSG_X11_REQUEST_FORWARDING); - } - packet_put_cstring(proto); - packet_put_cstring(new_data); - packet_put_int(screen_number); - packet_send(); - packet_write_wait(); + channel_request_start(ssh, client_session_id, "x11-req", want_reply); + if ((r = sshpkt_put_u8(ssh, 0)) != 0 || /* bool: single connection */ + (r = sshpkt_put_cstring(ssh, proto)) != 0 || + (r = sshpkt_put_cstring(ssh, new_data)) != 0 || + (r = sshpkt_put_u32(ssh, screen_number)) != 0 || + (r = sshpkt_send(ssh)) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) + fatal("%s: send x11-req: %s", __func__, ssh_err(r)); free(new_data); } - - -/* -- agent forwarding */ - -/* Sends a message to the server to request authentication fd forwarding. */ - -void -auth_request_forwarding(void) -{ - packet_start(SSH_CMSG_AGENT_REQUEST_FORWARDING); - packet_send(); - packet_write_wait(); -} diff --git a/channels.h b/channels.h index ce43236d5459..126b043454eb 100644 --- a/channels.h +++ b/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.121 2017/02/01 02:59:09 dtucker Exp $ */ +/* $OpenBSD: channels.h,v 1.130 2017/09/21 19:16:53 markus Exp $ */ /* * Author: Tatu Ylonen @@ -46,8 +46,6 @@ #define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */ #define SSH_CHANNEL_AUTH_SOCKET 6 /* authentication socket */ #define SSH_CHANNEL_X11_OPEN 7 /* reading first X11 packet */ -#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */ -#define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */ #define SSH_CHANNEL_LARVAL 10 /* larval session */ #define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */ #define SSH_CHANNEL_CONNECTING 12 @@ -59,22 +57,27 @@ #define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */ #define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */ #define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-slave */ -#define SSH_CHANNEL_MAX_TYPE 21 +#define SSH_CHANNEL_RDYNAMIC_OPEN 21 /* reverse SOCKS, parsing request */ +#define SSH_CHANNEL_RDYNAMIC_FINISH 22 /* reverse SOCKS, finishing connect */ +#define SSH_CHANNEL_MAX_TYPE 23 #define CHANNEL_CANCEL_PORT_STATIC -1 +struct ssh; struct Channel; typedef struct Channel Channel; +struct fwd_perm_list; -typedef void channel_open_fn(int, int, void *); -typedef void channel_callback_fn(int, void *); -typedef int channel_infilter_fn(struct Channel *, char *, int); -typedef void channel_filter_cleanup_fn(int, void *); -typedef u_char *channel_outfilter_fn(struct Channel *, u_char **, u_int *); +typedef void channel_open_fn(struct ssh *, int, int, void *); +typedef void channel_callback_fn(struct ssh *, int, void *); +typedef int channel_infilter_fn(struct ssh *, struct Channel *, char *, int); +typedef void channel_filter_cleanup_fn(struct ssh *, int, void *); +typedef u_char *channel_outfilter_fn(struct ssh *, struct Channel *, + u_char **, size_t *); /* Channel success/failure callbacks */ -typedef void channel_confirm_cb(int, struct Channel *, void *); -typedef void channel_confirm_abandon_cb(struct Channel *, void *); +typedef void channel_confirm_cb(struct ssh *, int, struct Channel *, void *); +typedef void channel_confirm_abandon_cb(struct ssh *, struct Channel *, void *); struct channel_confirm { TAILQ_ENTRY(channel_confirm) entry; channel_confirm_cb *cb; @@ -91,12 +94,14 @@ struct channel_connect { }; /* Callbacks for mux channels back into client-specific code */ -typedef int mux_callback_fn(struct Channel *); +typedef int mux_callback_fn(struct ssh *, struct Channel *); struct Channel { int type; /* channel type/state */ int self; /* my own channel identifier */ - int remote_id; /* channel identifier for remote peer */ + uint32_t remote_id; /* channel identifier for remote peer */ + int have_remote_id; /* non-zero if remote_id is valid */ + u_int istate; /* input from channel (state of receive half) */ u_int ostate; /* output to channel (state of transmit half) */ int flags; /* close sent/rcvd */ @@ -117,11 +122,12 @@ struct Channel { * to a matching pre-select handler. * this way post-select handlers are not * accidentally called if a FD gets reused */ - Buffer input; /* data read from socket, to be sent over + struct sshbuf *input; /* data read from socket, to be sent over * encrypted connection */ - Buffer output; /* data received over encrypted connection for + struct sshbuf *output; /* data received over encrypted connection for * send on socket */ - Buffer extended; + struct sshbuf *extended; + char *path; /* path for unix domain sockets, or host name for forwards */ int listening_port; /* port being listened for forwards */ @@ -157,6 +163,7 @@ struct Channel { int datagram; /* non-blocking connect */ + /* XXX make this a pointer so the structure can be opaque */ struct channel_connect connect_ctx; /* multiplexing protocol hook, called for each packet received */ @@ -196,128 +203,137 @@ struct Channel { #define CHAN_EOF_RCVD 0x08 #define CHAN_LOCAL 0x10 -#define CHAN_RBUF 16*1024 +/* Read buffer size */ +#define CHAN_RBUF (16*1024) + +/* Hard limit on number of channels */ +#define CHANNELS_MAX_CHANNELS (16*1024) /* check whether 'efd' is still in use */ #define CHANNEL_EFD_INPUT_ACTIVE(c) \ - (compat20 && c->extended_usage == CHAN_EXTENDED_READ && \ + (c->extended_usage == CHAN_EXTENDED_READ && \ (c->efd != -1 || \ - buffer_len(&c->extended) > 0)) + sshbuf_len(c->extended) > 0)) #define CHANNEL_EFD_OUTPUT_ACTIVE(c) \ - (compat20 && c->extended_usage == CHAN_EXTENDED_WRITE && \ + (c->extended_usage == CHAN_EXTENDED_WRITE && \ c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \ - buffer_len(&c->extended) > 0)) + sshbuf_len(c->extended) > 0)) + +/* Add channel management structures to SSH transport instance */ +void channel_init_channels(struct ssh *ssh); /* channel management */ -Channel *channel_by_id(int); -Channel *channel_by_remote_id(int); -Channel *channel_lookup(int); -Channel *channel_new(char *, int, int, int, int, u_int, u_int, int, char *, int); -void channel_set_fds(int, int, int, int, int, int, int, u_int); -void channel_free(Channel *); -void channel_free_all(void); -void channel_stop_listening(void); +Channel *channel_by_id(struct ssh *, int); +Channel *channel_by_remote_id(struct ssh *, u_int); +Channel *channel_lookup(struct ssh *, int); +Channel *channel_new(struct ssh *, char *, int, int, int, int, + u_int, u_int, int, char *, int); +void channel_set_fds(struct ssh *, int, int, int, int, int, + int, int, u_int); +void channel_free(struct ssh *, Channel *); +void channel_free_all(struct ssh *); +void channel_stop_listening(struct ssh *); -void channel_send_open(int); -void channel_request_start(int, char *, int); -void channel_register_cleanup(int, channel_callback_fn *, int); -void channel_register_open_confirm(int, channel_open_fn *, void *); -void channel_register_filter(int, channel_infilter_fn *, - channel_outfilter_fn *, channel_filter_cleanup_fn *, void *); -void channel_register_status_confirm(int, channel_confirm_cb *, - channel_confirm_abandon_cb *, void *); -void channel_cancel_cleanup(int); -int channel_close_fd(int *); -void channel_send_window_changes(void); +void channel_send_open(struct ssh *, int); +void channel_request_start(struct ssh *, int, char *, int); +void channel_register_cleanup(struct ssh *, int, + channel_callback_fn *, int); +void channel_register_open_confirm(struct ssh *, int, + channel_open_fn *, void *); +void channel_register_filter(struct ssh *, int, channel_infilter_fn *, + channel_outfilter_fn *, channel_filter_cleanup_fn *, void *); +void channel_register_status_confirm(struct ssh *, int, + channel_confirm_cb *, channel_confirm_abandon_cb *, void *); +void channel_cancel_cleanup(struct ssh *, int); +int channel_close_fd(struct ssh *, int *); +void channel_send_window_changes(struct ssh *); /* mux proxy support */ -int channel_proxy_downstream(Channel *mc); -int channel_proxy_upstream(Channel *, int, u_int32_t, void *); +int channel_proxy_downstream(struct ssh *, Channel *mc); +int channel_proxy_upstream(Channel *, int, u_int32_t, struct ssh *); /* protocol handler */ -int channel_input_close(int, u_int32_t, void *); -int channel_input_close_confirmation(int, u_int32_t, void *); -int channel_input_data(int, u_int32_t, void *); -int channel_input_extended_data(int, u_int32_t, void *); -int channel_input_ieof(int, u_int32_t, void *); -int channel_input_oclose(int, u_int32_t, void *); -int channel_input_open_confirmation(int, u_int32_t, void *); -int channel_input_open_failure(int, u_int32_t, void *); -int channel_input_port_open(int, u_int32_t, void *); -int channel_input_window_adjust(int, u_int32_t, void *); -int channel_input_status_confirm(int, u_int32_t, void *); +int channel_input_data(int, u_int32_t, struct ssh *); +int channel_input_extended_data(int, u_int32_t, struct ssh *); +int channel_input_ieof(int, u_int32_t, struct ssh *); +int channel_input_oclose(int, u_int32_t, struct ssh *); +int channel_input_open_confirmation(int, u_int32_t, struct ssh *); +int channel_input_open_failure(int, u_int32_t, struct ssh *); +int channel_input_port_open(int, u_int32_t, struct ssh *); +int channel_input_window_adjust(int, u_int32_t, struct ssh *); +int channel_input_status_confirm(int, u_int32_t, struct ssh *); /* file descriptor handling (read/write) */ -void channel_prepare_select(fd_set **, fd_set **, int *, u_int*, - time_t*, int); -void channel_after_select(fd_set *, fd_set *); -void channel_output_poll(void); +void channel_prepare_select(struct ssh *, fd_set **, fd_set **, int *, + u_int*, time_t*); +void channel_after_select(struct ssh *, fd_set *, fd_set *); +void channel_output_poll(struct ssh *); -int channel_not_very_much_buffered_data(void); -void channel_close_all(void); -int channel_still_open(void); -char *channel_open_message(void); -int channel_find_open(void); +int channel_not_very_much_buffered_data(struct ssh *); +void channel_close_all(struct ssh *); +int channel_still_open(struct ssh *); +char *channel_open_message(struct ssh *); +int channel_find_open(struct ssh *); /* tcp forwarding */ struct Forward; struct ForwardOptions; -void channel_set_af(int af); -void channel_permit_all_opens(void); -void channel_add_permitted_opens(char *, int); -int channel_add_adm_permitted_opens(char *, int); -void channel_disable_adm_local_opens(void); -void channel_update_permitted_opens(int, int); -void channel_clear_permitted_opens(void); -void channel_clear_adm_permitted_opens(void); -void channel_print_adm_permitted_opens(void); -Channel *channel_connect_to_port(const char *, u_short, char *, char *, int *, - const char **); -Channel *channel_connect_to_path(const char *, char *, char *); -Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); -Channel *channel_connect_by_listen_address(const char *, u_short, - char *, char *); -Channel *channel_connect_by_listen_path(const char *, char *, char *); -int channel_request_remote_forwarding(struct Forward *); -int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *); -int channel_request_rforward_cancel(struct Forward *); -int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *); -int channel_cancel_rport_listener(struct Forward *); -int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *); +void channel_set_af(struct ssh *, int af); +void channel_permit_all_opens(struct ssh *); +void channel_add_permitted_opens(struct ssh *, char *, int); +int channel_add_adm_permitted_opens(struct ssh *, char *, int); +void channel_copy_adm_permitted_opens(struct ssh *, + const struct fwd_perm_list *); +void channel_disable_adm_local_opens(struct ssh *); +void channel_update_permitted_opens(struct ssh *, int, int); +void channel_clear_permitted_opens(struct ssh *); +void channel_clear_adm_permitted_opens(struct ssh *); +void channel_print_adm_permitted_opens(struct ssh *); +Channel *channel_connect_to_port(struct ssh *, const char *, u_short, + char *, char *, int *, const char **); +Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *); +Channel *channel_connect_stdio_fwd(struct ssh *, const char*, + u_short, int, int); +Channel *channel_connect_by_listen_address(struct ssh *, const char *, + u_short, char *, char *); +Channel *channel_connect_by_listen_path(struct ssh *, const char *, + char *, char *); +int channel_request_remote_forwarding(struct ssh *, struct Forward *); +int channel_setup_local_fwd_listener(struct ssh *, struct Forward *, + struct ForwardOptions *); +int channel_request_rforward_cancel(struct ssh *, struct Forward *); +int channel_setup_remote_fwd_listener(struct ssh *, struct Forward *, + int *, struct ForwardOptions *); +int channel_cancel_rport_listener(struct ssh *, struct Forward *); +int channel_cancel_lport_listener(struct ssh *, struct Forward *, + int, struct ForwardOptions *); int permitopen_port(const char *); /* x11 forwarding */ -void channel_set_x11_refuse_time(u_int); -int x11_connect_display(void); -int x11_create_display_inet(int, int, int, u_int *, int **); -int x11_input_open(int, u_int32_t, void *); -void x11_request_forwarding_with_spoofing(int, const char *, const char *, - const char *, int); -int deny_input_open(int, u_int32_t, void *); - -/* agent forwarding */ - -void auth_request_forwarding(void); +void channel_set_x11_refuse_time(struct ssh *, u_int); +int x11_connect_display(struct ssh *); +int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **); +void x11_request_forwarding_with_spoofing(struct ssh *, int, + const char *, const char *, const char *, int); /* channel close */ -int chan_is_dead(Channel *, int); -void chan_mark_dead(Channel *); +int chan_is_dead(struct ssh *, Channel *, int); +void chan_mark_dead(struct ssh *, Channel *); /* channel events */ -void chan_rcvd_oclose(Channel *); -void chan_rcvd_eow(Channel *); /* SSH2-only */ -void chan_read_failed(Channel *); -void chan_ibuf_empty(Channel *); - -void chan_rcvd_ieof(Channel *); -void chan_write_failed(Channel *); -void chan_obuf_empty(Channel *); +void chan_rcvd_oclose(struct ssh *, Channel *); +void chan_rcvd_eow(struct ssh *, Channel *); +void chan_read_failed(struct ssh *, Channel *); +void chan_ibuf_empty(struct ssh *, Channel *); +void chan_rcvd_ieof(struct ssh *, Channel *); +void chan_write_failed(struct ssh *, Channel *); +void chan_obuf_empty(struct ssh *, Channel *); #endif diff --git a/cipher-3des1.c b/cipher-3des1.c deleted file mode 100644 index 9fcc2785a3fb..000000000000 --- a/cipher-3des1.c +++ /dev/null @@ -1,158 +0,0 @@ -/* $OpenBSD: cipher-3des1.c,v 1.12 2015/01/14 10:24:42 markus Exp $ */ -/* - * Copyright (c) 2003 Markus Friedl. All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#ifdef WITH_SSH1 - -#include -#include -#include - -#include "ssherr.h" - -/* - * This is used by SSH1: - * - * What kind of triple DES are these 2 routines? - * - * Why is there a redundant initialization vector? - * - * If only iv3 was used, then, this would till effect have been - * outer-cbc. However, there is also a private iv1 == iv2 which - * perhaps makes differential analysis easier. On the other hand, the - * private iv1 probably makes the CRC-32 attack ineffective. This is a - * result of that there is no longer any known iv1 to use when - * choosing the X block. - */ -struct ssh1_3des_ctx -{ - EVP_CIPHER_CTX k1, k2, k3; -}; - -const EVP_CIPHER * evp_ssh1_3des(void); -int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); - -static int -ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, - int enc) -{ - struct ssh1_3des_ctx *c; - u_char *k1, *k2, *k3; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { - if ((c = calloc(1, sizeof(*c))) == NULL) - return 0; - EVP_CIPHER_CTX_set_app_data(ctx, c); - } - if (key == NULL) - return 1; - if (enc == -1) - enc = ctx->encrypt; - k1 = k2 = k3 = (u_char *) key; - k2 += 8; - if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) { - if (enc) - k3 += 16; - else - k1 += 16; - } - EVP_CIPHER_CTX_init(&c->k1); - EVP_CIPHER_CTX_init(&c->k2); - EVP_CIPHER_CTX_init(&c->k3); - if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 || - EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 || - EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) { - explicit_bzero(c, sizeof(*c)); - free(c); - EVP_CIPHER_CTX_set_app_data(ctx, NULL); - return 0; - } - return 1; -} - -static int -ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, size_t len) -{ - struct ssh1_3des_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) - return 0; - if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 || - EVP_Cipher(&c->k2, dest, dest, len) == 0 || - EVP_Cipher(&c->k3, dest, dest, len) == 0) - return 0; - return 1; -} - -static int -ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx) -{ - struct ssh1_3des_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { - EVP_CIPHER_CTX_cleanup(&c->k1); - EVP_CIPHER_CTX_cleanup(&c->k2); - EVP_CIPHER_CTX_cleanup(&c->k3); - explicit_bzero(c, sizeof(*c)); - free(c); - EVP_CIPHER_CTX_set_app_data(ctx, NULL); - } - return 1; -} - -int -ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len) -{ - struct ssh1_3des_ctx *c; - - if (len != 24) - return SSH_ERR_INVALID_ARGUMENT; - if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) - return SSH_ERR_INTERNAL_ERROR; - if (doset) { - memcpy(c->k1.iv, iv, 8); - memcpy(c->k2.iv, iv + 8, 8); - memcpy(c->k3.iv, iv + 16, 8); - } else { - memcpy(iv, c->k1.iv, 8); - memcpy(iv + 8, c->k2.iv, 8); - memcpy(iv + 16, c->k3.iv, 8); - } - return 0; -} - -const EVP_CIPHER * -evp_ssh1_3des(void) -{ - static EVP_CIPHER ssh1_3des; - - memset(&ssh1_3des, 0, sizeof(ssh1_3des)); - ssh1_3des.nid = NID_undef; - ssh1_3des.block_size = 8; - ssh1_3des.iv_len = 0; - ssh1_3des.key_len = 16; - ssh1_3des.init = ssh1_3des_init; - ssh1_3des.cleanup = ssh1_3des_cleanup; - ssh1_3des.do_cipher = ssh1_3des_cbc; - ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH; - return &ssh1_3des; -} -#endif /* WITH_SSH1 */ diff --git a/cipher-bf1.c b/cipher-bf1.c deleted file mode 100644 index c205b077ca42..000000000000 --- a/cipher-bf1.c +++ /dev/null @@ -1,106 +0,0 @@ -/* $OpenBSD: cipher-bf1.c,v 1.7 2015/01/14 10:24:42 markus Exp $ */ -/* - * Copyright (c) 2003 Markus Friedl. All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#ifdef WITH_SSH1 -#if defined(WITH_OPENSSL) && !defined(OPENSSL_NO_BF) - -#include - -#include -#include - -#include - -#include "openbsd-compat/openssl-compat.h" - -/* - * SSH1 uses a variation on Blowfish, all bytes must be swapped before - * and after encryption/decryption. Thus the swap_bytes stuff (yuk). - */ - -const EVP_CIPHER * evp_ssh1_bf(void); - -static void -swap_bytes(const u_char *src, u_char *dst, int n) -{ - u_char c[4]; - - /* Process 4 bytes every lap. */ - for (n = n / 4; n > 0; n--) { - c[3] = *src++; - c[2] = *src++; - c[1] = *src++; - c[0] = *src++; - - *dst++ = c[0]; - *dst++ = c[1]; - *dst++ = c[2]; - *dst++ = c[3]; - } -} - -#ifdef SSH_OLD_EVP -static void bf_ssh1_init (EVP_CIPHER_CTX * ctx, const unsigned char *key, - const unsigned char *iv, int enc) -{ - if (iv != NULL) - memcpy (&(ctx->oiv[0]), iv, 8); - memcpy (&(ctx->iv[0]), &(ctx->oiv[0]), 8); - if (key != NULL) - BF_set_key (&(ctx->c.bf_ks), EVP_CIPHER_CTX_key_length (ctx), - key); -} -#endif - -static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, - const u_char *, LIBCRYPTO_EVP_INL_TYPE) = NULL; - -static int -bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, - LIBCRYPTO_EVP_INL_TYPE len) -{ - int ret; - - swap_bytes(in, out, len); - ret = (*orig_bf)(ctx, out, out, len); - swap_bytes(out, out, len); - return (ret); -} - -const EVP_CIPHER * -evp_ssh1_bf(void) -{ - static EVP_CIPHER ssh1_bf; - - memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER)); - orig_bf = ssh1_bf.do_cipher; - ssh1_bf.nid = NID_undef; -#ifdef SSH_OLD_EVP - ssh1_bf.init = bf_ssh1_init; -#endif - ssh1_bf.do_cipher = bf_ssh1_cipher; - ssh1_bf.key_len = 32; - return (&ssh1_bf); -} -#endif /* defined(WITH_OPENSSL) && !defined(OPENSSL_NO_BF) */ - -#endif /* WITH_SSH1 */ diff --git a/cipher.c b/cipher.c index 2def333b14d2..c3cd5dcf4405 100644 --- a/cipher.c +++ b/cipher.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.c,v 1.102 2016/08/03 05:41:57 djm Exp $ */ +/* $OpenBSD: cipher.c,v 1.107 2017/05/07 23:12:57 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -51,11 +51,6 @@ #include "openbsd-compat/openssl-compat.h" -#ifdef WITH_SSH1 -extern const EVP_CIPHER *evp_ssh1_bf(void); -extern const EVP_CIPHER *evp_ssh1_3des(void); -extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); -#endif struct sshcipher_ctx { int plaintext; @@ -68,17 +63,16 @@ struct sshcipher_ctx { struct sshcipher { char *name; - int number; /* for ssh1 only */ u_int block_size; u_int key_len; u_int iv_len; /* defaults to block_size */ u_int auth_len; - u_int discard_len; u_int flags; #define CFLAG_CBC (1<<0) #define CFLAG_CHACHAPOLY (1<<1) #define CFLAG_AESCTR (1<<2) #define CFLAG_NONE (1<<3) +#define CFLAG_INTERNAL CFLAG_NONE /* Don't use "none" for packets */ #ifdef WITH_OPENSSL const EVP_CIPHER *(*evptype)(void); #else @@ -87,53 +81,32 @@ struct sshcipher { }; static const struct sshcipher ciphers[] = { -#ifdef WITH_SSH1 - { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, - { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, -# ifndef OPENSSL_NO_BF - { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf }, -# endif /* OPENSSL_NO_BF */ -#endif /* WITH_SSH1 */ #ifdef WITH_OPENSSL - { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, - { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, -# ifndef OPENSSL_NO_BF - { "blowfish-cbc", - SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc }, -# endif /* OPENSSL_NO_BF */ -# ifndef OPENSSL_NO_CAST - { "cast128-cbc", - SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_cast5_cbc }, -# endif /* OPENSSL_NO_CAST */ -# ifndef OPENSSL_NO_RC4 - { "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 0, EVP_rc4 }, - { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 0, 0, 1536, 0, EVP_rc4 }, - { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 0, 0, 1536, 0, EVP_rc4 }, -# endif /* OPENSSL_NO_RC4 */ - { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc }, - { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc }, - { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, + { "3des-cbc", 8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc }, + { "aes128-cbc", 16, 16, 0, 0, CFLAG_CBC, EVP_aes_128_cbc }, + { "aes192-cbc", 16, 24, 0, 0, CFLAG_CBC, EVP_aes_192_cbc }, + { "aes256-cbc", 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc }, { "rijndael-cbc@lysator.liu.se", - SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, - { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, - { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr }, - { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr }, + 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc }, + { "aes128-ctr", 16, 16, 0, 0, 0, EVP_aes_128_ctr }, + { "aes192-ctr", 16, 24, 0, 0, 0, EVP_aes_192_ctr }, + { "aes256-ctr", 16, 32, 0, 0, 0, EVP_aes_256_ctr }, # ifdef OPENSSL_HAVE_EVPGCM { "aes128-gcm@openssh.com", - SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, + 16, 16, 12, 16, 0, EVP_aes_128_gcm }, { "aes256-gcm@openssh.com", - SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, + 16, 32, 12, 16, 0, EVP_aes_256_gcm }, # endif /* OPENSSL_HAVE_EVPGCM */ -#else /* WITH_OPENSSL */ - { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL }, - { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL }, - { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, CFLAG_AESCTR, NULL }, - { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, CFLAG_NONE, NULL }, -#endif /* WITH_OPENSSL */ +#else + { "aes128-ctr", 16, 16, 0, 0, CFLAG_AESCTR, NULL }, + { "aes192-ctr", 16, 24, 0, 0, CFLAG_AESCTR, NULL }, + { "aes256-ctr", 16, 32, 0, 0, CFLAG_AESCTR, NULL }, +#endif { "chacha20-poly1305@openssh.com", - SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL }, + 8, 64, 0, 16, CFLAG_CHACHAPOLY, NULL }, + { "none", 8, 0, 0, 0, CFLAG_NONE, NULL }, - { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } + { NULL, 0, 0, 0, 0, 0, NULL } }; /*--*/ @@ -147,7 +120,7 @@ cipher_alg_list(char sep, int auth_only) const struct sshcipher *c; for (c = ciphers; c->name != NULL; c++) { - if (c->number != SSH_CIPHER_SSH2) + if ((c->flags & CFLAG_INTERNAL) != 0) continue; if (auth_only && c->auth_len == 0) continue; @@ -202,12 +175,6 @@ cipher_ivlen(const struct sshcipher *c) c->iv_len : c->block_size; } -u_int -cipher_get_number(const struct sshcipher *c) -{ - return (c->number); -} - u_int cipher_is_cbc(const struct sshcipher *c) { @@ -220,24 +187,6 @@ cipher_ctx_is_plaintext(struct sshcipher_ctx *cc) return cc->plaintext; } -u_int -cipher_ctx_get_number(struct sshcipher_ctx *cc) -{ - return cc->cipher->number; -} - -u_int -cipher_mask_ssh1(int client) -{ - u_int mask = 0; - mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */ - mask |= 1 << SSH_CIPHER_BLOWFISH; - if (client) { - mask |= 1 << SSH_CIPHER_DES; - } - return mask; -} - const struct sshcipher * cipher_by_name(const char *name) { @@ -248,16 +197,6 @@ cipher_by_name(const char *name) return NULL; } -const struct sshcipher * -cipher_by_number(int id) -{ - const struct sshcipher *c; - for (c = ciphers; c->name != NULL; c++) - if (c->number == id) - return c; - return NULL; -} - #define CIPHER_SEP "," int ciphers_valid(const char *names) @@ -273,7 +212,7 @@ ciphers_valid(const char *names) for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; (p = strsep(&cp, CIPHER_SEP))) { c = cipher_by_name(p); - if (c == NULL || c->number != SSH_CIPHER_SSH2) { + if (c == NULL || (c->flags & CFLAG_INTERNAL) != 0) { free(cipher_list); return 0; } @@ -282,38 +221,12 @@ ciphers_valid(const char *names) return 1; } -/* - * Parses the name of the cipher. Returns the number of the corresponding - * cipher, or -1 on error. - */ - -int -cipher_number(const char *name) -{ - const struct sshcipher *c; - if (name == NULL) - return -1; - for (c = ciphers; c->name != NULL; c++) - if (strcasecmp(c->name, name) == 0) - return c->number; - return -1; -} - -char * -cipher_name(int id) -{ - const struct sshcipher *c = cipher_by_number(id); - return (c==NULL) ? "" : c->name; -} - const char * cipher_warning_message(const struct sshcipher_ctx *cc) { if (cc == NULL || cc->cipher == NULL) return NULL; - if (cc->cipher->number == SSH_CIPHER_DES) - return "use of DES is strongly discouraged due to " - "cryptographic weaknesses"; + /* XXX repurpose for CBC warning */ return NULL; } @@ -327,19 +240,13 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher, #ifdef WITH_OPENSSL const EVP_CIPHER *type; int klen; - u_char *junk, *discard; #endif *ccp = NULL; if ((cc = calloc(sizeof(*cc), 1)) == NULL) return SSH_ERR_ALLOC_FAIL; - if (cipher->number == SSH_CIPHER_DES) { - if (keylen > 8) - keylen = 8; - } - - cc->plaintext = (cipher->number == SSH_CIPHER_NONE); + cc->plaintext = (cipher->flags & CFLAG_NONE) != 0; cc->encrypt = do_encrypt; if (keylen < cipher->key_len || @@ -353,6 +260,10 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher, ret = chachapoly_init(&cc->cp_ctx, key, keylen); goto out; } + if ((cc->cipher->flags & CFLAG_NONE) != 0) { + ret = 0; + goto out; + } #ifndef WITH_OPENSSL if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen); @@ -360,10 +271,6 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher, ret = 0; goto out; } - if ((cc->cipher->flags & CFLAG_NONE) != 0) { - ret = 0; - goto out; - } ret = SSH_ERR_INVALID_ARGUMENT; goto out; #else /* WITH_OPENSSL */ @@ -394,23 +301,6 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher, ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } - - if (cipher->discard_len > 0) { - if ((junk = malloc(cipher->discard_len)) == NULL || - (discard = malloc(cipher->discard_len)) == NULL) { - free(junk); - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - ret = EVP_Cipher(cc->evp, discard, junk, cipher->discard_len); - explicit_bzero(discard, cipher->discard_len); - free(junk); - free(discard); - if (ret != 1) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - } ret = 0; #endif /* WITH_OPENSSL */ out: @@ -448,6 +338,10 @@ cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest, return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, len, aadlen, authlen, cc->encrypt); } + if ((cc->cipher->flags & CFLAG_NONE) != 0) { + memcpy(dest, src, aadlen + len); + return 0; + } #ifndef WITH_OPENSSL if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { if (aadlen) @@ -456,10 +350,6 @@ cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest, dest + aadlen, len); return 0; } - if ((cc->cipher->flags & CFLAG_NONE) != 0) { - memcpy(dest, src, aadlen + len); - return 0; - } return SSH_ERR_INVALID_ARGUMENT; #else if (authlen) { @@ -535,28 +425,6 @@ cipher_free(struct sshcipher_ctx *cc) free(cc); } -/* - * Selects the cipher, and keys if by computing the MD5 checksum of the - * passphrase and using the resulting 16 bytes as the key. - */ -int -cipher_set_key_string(struct sshcipher_ctx **ccp, - const struct sshcipher *cipher, const char *passphrase, int do_encrypt) -{ - u_char digest[16]; - int r = SSH_ERR_INTERNAL_ERROR; - - if ((r = ssh_digest_memory(SSH_DIGEST_MD5, - passphrase, strlen(passphrase), - digest, sizeof(digest))) != 0) - goto out; - - r = cipher_init(ccp, cipher, digest, 16, NULL, 0, do_encrypt); - out: - explicit_bzero(digest, sizeof(digest)); - return r; -} - /* * Exports an IV from the sshcipher_ctx required to export the key * state back from the unprivileged child to the privileged parent @@ -566,19 +434,16 @@ int cipher_get_keyiv_len(const struct sshcipher_ctx *cc) { const struct sshcipher *c = cc->cipher; - int ivlen = 0; - if (c->number == SSH_CIPHER_3DES) - ivlen = 24; - else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) - ivlen = 0; - else if ((cc->cipher->flags & CFLAG_AESCTR) != 0) - ivlen = sizeof(cc->ac_ctx.ctr); + if ((c->flags & CFLAG_CHACHAPOLY) != 0) + return 0; + else if ((c->flags & CFLAG_AESCTR) != 0) + return sizeof(cc->ac_ctx.ctr); #ifdef WITH_OPENSSL - else - ivlen = EVP_CIPHER_CTX_iv_length(cc->evp); -#endif /* WITH_OPENSSL */ - return (ivlen); + return EVP_CIPHER_CTX_iv_length(cc->evp); +#else + return 0; +#endif } int @@ -603,38 +468,26 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len) if ((cc->cipher->flags & CFLAG_NONE) != 0) return 0; - switch (c->number) { #ifdef WITH_OPENSSL - case SSH_CIPHER_SSH2: - case SSH_CIPHER_DES: - case SSH_CIPHER_BLOWFISH: - evplen = EVP_CIPHER_CTX_iv_length(cc->evp); - if (evplen == 0) - return 0; - else if (evplen < 0) - return SSH_ERR_LIBCRYPTO_ERROR; - if ((u_int)evplen != len) - return SSH_ERR_INVALID_ARGUMENT; -#ifndef OPENSSL_HAVE_EVPCTR - if (c->evptype == evp_aes_128_ctr) - ssh_aes_ctr_iv(cc->evp, 0, iv, len); - else -#endif - if (cipher_authlen(c)) { - if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, - len, iv)) - return SSH_ERR_LIBCRYPTO_ERROR; - } else - memcpy(iv, cc->evp->iv, len); - break; -#endif -#ifdef WITH_SSH1 - case SSH_CIPHER_3DES: - return ssh1_3des_iv(cc->evp, 0, iv, 24); -#endif - default: + evplen = EVP_CIPHER_CTX_iv_length(cc->evp); + if (evplen == 0) + return 0; + else if (evplen < 0) + return SSH_ERR_LIBCRYPTO_ERROR; + if ((u_int)evplen != len) return SSH_ERR_INVALID_ARGUMENT; - } +#ifndef OPENSSL_HAVE_EVPCTR + if (c->evptype == evp_aes_128_ctr) + ssh_aes_ctr_iv(cc->evp, 0, iv, len); + else +#endif + if (cipher_authlen(c)) { + if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, + len, iv)) + return SSH_ERR_LIBCRYPTO_ERROR; + } else + memcpy(iv, cc->evp->iv, len); +#endif return 0; } @@ -651,36 +504,24 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv) if ((cc->cipher->flags & CFLAG_NONE) != 0) return 0; - switch (c->number) { #ifdef WITH_OPENSSL - case SSH_CIPHER_SSH2: - case SSH_CIPHER_DES: - case SSH_CIPHER_BLOWFISH: - evplen = EVP_CIPHER_CTX_iv_length(cc->evp); - if (evplen <= 0) - return SSH_ERR_LIBCRYPTO_ERROR; + evplen = EVP_CIPHER_CTX_iv_length(cc->evp); + if (evplen <= 0) + return SSH_ERR_LIBCRYPTO_ERROR; #ifndef OPENSSL_HAVE_EVPCTR - /* XXX iv arg is const, but ssh_aes_ctr_iv isn't */ - if (c->evptype == evp_aes_128_ctr) - ssh_aes_ctr_iv(cc->evp, 1, (u_char *)iv, evplen); - else + /* XXX iv arg is const, but ssh_aes_ctr_iv isn't */ + if (c->evptype == evp_aes_128_ctr) + ssh_aes_ctr_iv(cc->evp, 1, (u_char *)iv, evplen); + else #endif - if (cipher_authlen(c)) { - /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */ - if (!EVP_CIPHER_CTX_ctrl(cc->evp, - EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv)) - return SSH_ERR_LIBCRYPTO_ERROR; - } else - memcpy(cc->evp->iv, iv, evplen); - break; + if (cipher_authlen(c)) { + /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */ + if (!EVP_CIPHER_CTX_ctrl(cc->evp, + EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv)) + return SSH_ERR_LIBCRYPTO_ERROR; + } else + memcpy(cc->evp->iv, iv, evplen); #endif -#ifdef WITH_SSH1 - case SSH_CIPHER_3DES: - return ssh1_3des_iv(cc->evp, 1, (u_char *)iv, 24); -#endif - default: - return SSH_ERR_INVALID_ARGUMENT; - } return 0; } diff --git a/cipher.h b/cipher.h index f4bca6285fa3..dc7ecf1139d4 100644 --- a/cipher.h +++ b/cipher.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.h,v 1.49 2016/08/03 05:41:57 djm Exp $ */ +/* $OpenBSD: cipher.h,v 1.52 2017/05/07 23:12:57 djm Exp $ */ /* * Author: Tatu Ylonen @@ -42,34 +42,13 @@ #include "cipher-chachapoly.h" #include "cipher-aesctr.h" -/* - * Cipher types for SSH-1. New types can be added, but old types should not - * be removed for compatibility. The maximum allowed value is 31. - */ -#define SSH_CIPHER_SSH2 -3 -#define SSH_CIPHER_INVALID -2 /* No valid cipher selected. */ -#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */ -#define SSH_CIPHER_NONE 0 /* no encryption */ -#define SSH_CIPHER_IDEA 1 /* IDEA CFB */ -#define SSH_CIPHER_DES 2 /* DES CBC */ -#define SSH_CIPHER_3DES 3 /* 3DES CBC */ -#define SSH_CIPHER_BROKEN_TSS 4 /* TRI's Simple Stream encryption CBC */ -#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */ -#define SSH_CIPHER_BLOWFISH 6 -#define SSH_CIPHER_RESERVED 7 -#define SSH_CIPHER_MAX 31 - #define CIPHER_ENCRYPT 1 #define CIPHER_DECRYPT 0 struct sshcipher; struct sshcipher_ctx; -u_int cipher_mask_ssh1(int); const struct sshcipher *cipher_by_name(const char *); -const struct sshcipher *cipher_by_number(int); -int cipher_number(const char *); -char *cipher_name(int); const char *cipher_warning_message(const struct sshcipher_ctx *); int ciphers_valid(const char *); char *cipher_alg_list(char, int); @@ -80,8 +59,6 @@ int cipher_crypt(struct sshcipher_ctx *, u_int, u_char *, const u_char *, int cipher_get_length(struct sshcipher_ctx *, u_int *, u_int, const u_char *, u_int); void cipher_free(struct sshcipher_ctx *); -int cipher_set_key_string(struct sshcipher_ctx **, - const struct sshcipher *, const char *, int); u_int cipher_blocksize(const struct sshcipher *); u_int cipher_keylen(const struct sshcipher *); u_int cipher_seclen(const struct sshcipher *); @@ -90,13 +67,9 @@ u_int cipher_ivlen(const struct sshcipher *); u_int cipher_is_cbc(const struct sshcipher *); u_int cipher_ctx_is_plaintext(struct sshcipher_ctx *); -u_int cipher_ctx_get_number(struct sshcipher_ctx *); -u_int cipher_get_number(const struct sshcipher *); int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, u_int); int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *); int cipher_get_keyiv_len(const struct sshcipher_ctx *); -int cipher_get_keycontext(const struct sshcipher_ctx *, u_char *); -void cipher_set_keycontext(struct sshcipher_ctx *, const u_char *); #endif /* CIPHER_H */ diff --git a/clientloop.c b/clientloop.c index 0648162341f7..791d336e359e 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.291 2017/03/10 05:01:13 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.305 2017/09/19 04:24:22 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -89,7 +89,6 @@ #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" -#include "ssh1.h" #include "ssh2.h" #include "packet.h" #include "buffer.h" @@ -152,15 +151,9 @@ static time_t control_persist_exit_time = 0; /* Common data for the client loop code. */ volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ -static int escape_char1; /* Escape character. (proto1 only) */ -static int escape_pending1; /* Last character was an escape (proto1 only) */ static int last_was_cr; /* Last character was a newline. */ static int exit_status; /* Used to store the command exit status. */ -static int stdin_eof; /* EOF has been encountered on stderr. */ -static Buffer stdin_buffer; /* Buffer for stdin data. */ -static Buffer stdout_buffer; /* Buffer for stdout data. */ -static Buffer stderr_buffer; /* Buffer for stderr data. */ -static u_int buffer_high; /* Soft max buffer size. */ +static Buffer stderr_buffer; /* Used for final exit message. */ static int connection_in; /* Connection to server (input). */ static int connection_out; /* Connection to server (output). */ static int need_rekeying; /* Set to non-zero if rekeying is requested. */ @@ -184,6 +177,7 @@ struct channel_reply_ctx { }; /* Global request success/failure callbacks */ +/* XXX move to struct ssh? */ struct global_confirm { TAILQ_ENTRY(global_confirm) entry; global_confirm_cb *cb; @@ -207,15 +201,6 @@ leave_non_blocking(void) } } -/* Puts stdin terminal in non-blocking mode. */ - -static void -enter_non_blocking(void) -{ - in_non_blocking_mode = 1; - set_nonblock(fileno(stdin)); -} - /* * Signal handler for the window change signal (SIGWINCH). This just sets a * flag indicating that the window has changed. @@ -260,13 +245,13 @@ get_current_time(void) * control master process, or if there is no ControlPersist timeout. */ static void -set_control_persist_exit_time(void) +set_control_persist_exit_time(struct ssh *ssh) { if (muxserver_sock == -1 || !options.control_persist || options.control_persist_timeout == 0) { /* not using a ControlPersist timeout */ control_persist_exit_time = 0; - } else if (channel_still_open()) { + } else if (channel_still_open(ssh)) { /* some client connections are still open */ if (control_persist_exit_time > 0) debug2("%s: cancel scheduled exit", __func__); @@ -304,8 +289,9 @@ client_x11_display_valid(const char *display) #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" #define X11_TIMEOUT_SLACK 60 int -client_x11_get_proto(const char *display, const char *xauth_path, - u_int trusted, u_int timeout, char **_proto, char **_data) +client_x11_get_proto(struct ssh *ssh, const char *display, + const char *xauth_path, u_int trusted, u_int timeout, + char **_proto, char **_data) { char cmd[1024], line[512], xdisplay[512]; char xauthfile[PATH_MAX], xauthdir[PATH_MAX]; @@ -389,7 +375,8 @@ client_x11_get_proto(const char *display, const char *xauth_path, x11_refuse_time = UINT_MAX; else x11_refuse_time = now + timeout; - channel_set_x11_refuse_time(x11_refuse_time); + channel_set_x11_refuse_time(ssh, + x11_refuse_time); } if (system(cmd) == 0) generated = 1; @@ -454,91 +441,6 @@ client_x11_get_proto(const char *display, const char *xauth_path, return 0; } -/* - * This is called when the interactive is entered. This checks if there is - * an EOF coming on stdin. We must check this explicitly, as select() does - * not appear to wake up when redirecting from /dev/null. - */ - -static void -client_check_initial_eof_on_stdin(void) -{ - int len; - char buf[1]; - - /* - * If standard input is to be "redirected from /dev/null", we simply - * mark that we have seen an EOF and send an EOF message to the - * server. Otherwise, we try to read a single character; it appears - * that for some files, such /dev/null, select() never wakes up for - * read for this descriptor, which means that we never get EOF. This - * way we will get the EOF if stdin comes from /dev/null or similar. - */ - if (stdin_null_flag) { - /* Fake EOF on stdin. */ - debug("Sending eof."); - stdin_eof = 1; - packet_start(SSH_CMSG_EOF); - packet_send(); - } else { - enter_non_blocking(); - - /* Check for immediate EOF on stdin. */ - len = read(fileno(stdin), buf, 1); - if (len == 0) { - /* - * EOF. Record that we have seen it and send - * EOF to server. - */ - debug("Sending eof."); - stdin_eof = 1; - packet_start(SSH_CMSG_EOF); - packet_send(); - } else if (len > 0) { - /* - * Got data. We must store the data in the buffer, - * and also process it as an escape character if - * appropriate. - */ - if ((u_char) buf[0] == escape_char1) - escape_pending1 = 1; - else - buffer_append(&stdin_buffer, buf, 1); - } - leave_non_blocking(); - } -} - - -/* - * Make packets from buffered stdin data, and buffer them for sending to the - * connection. - */ - -static void -client_make_packets_from_stdin_data(void) -{ - u_int len; - - /* Send buffered stdin data to the server. */ - while (buffer_len(&stdin_buffer) > 0 && - packet_not_very_much_data_to_write()) { - len = buffer_len(&stdin_buffer); - /* Keep the packets at reasonable size. */ - if (len > packet_get_maxsize()) - len = packet_get_maxsize(); - packet_start(SSH_CMSG_STDIN_DATA); - packet_put_string(buffer_ptr(&stdin_buffer), len); - packet_send(); - buffer_consume(&stdin_buffer, len); - /* If we have a pending EOF, send it now. */ - if (stdin_eof && buffer_len(&stdin_buffer) == 0) { - packet_start(SSH_CMSG_EOF); - packet_send(); - } - } -} - /* * Checks if the client window has changed, and sends a packet about it to * the server if so. The actual change is detected elsewhere (by a software @@ -547,40 +449,27 @@ client_make_packets_from_stdin_data(void) */ static void -client_check_window_change(void) +client_check_window_change(struct ssh *ssh) { - struct winsize ws; - - if (! received_window_change_signal) + if (!received_window_change_signal) return; /** XXX race */ received_window_change_signal = 0; - debug2("client_check_window_change: changed"); + debug2("%s: changed", __func__); - if (compat20) { - channel_send_window_changes(); - } else { - if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) - return; - packet_start(SSH_CMSG_WINDOW_SIZE); - packet_put_int((u_int)ws.ws_row); - packet_put_int((u_int)ws.ws_col); - packet_put_int((u_int)ws.ws_xpixel); - packet_put_int((u_int)ws.ws_ypixel); - packet_send(); - } + channel_send_window_changes(ssh); } static int -client_global_request_reply(int type, u_int32_t seq, void *ctxt) +client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh) { struct global_confirm *gc; if ((gc = TAILQ_FIRST(&global_confirms)) == NULL) return 0; if (gc->cb != NULL) - gc->cb(type, seq, gc->ctx); + gc->cb(ssh, type, seq, gc->ctx); if (--gc->ref_count <= 0) { TAILQ_REMOVE(&global_confirms, gc, entry); explicit_bzero(gc, sizeof(*gc)); @@ -611,7 +500,8 @@ server_alive_check(void) * one of the file descriptors). */ static void -client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, +client_wait_until_can_do_something(struct ssh *ssh, + fd_set **readsetp, fd_set **writesetp, int *maxfdp, u_int *nallocp, int rekeying) { struct timeval tv, *tvp; @@ -620,40 +510,20 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int ret; /* Add any selections by the channel mechanism. */ - channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, - &minwait_secs, rekeying); + channel_prepare_select(active_state, readsetp, writesetp, maxfdp, + nallocp, &minwait_secs); - if (!compat20) { - /* Read from the connection, unless our buffers are full. */ - if (buffer_len(&stdout_buffer) < buffer_high && - buffer_len(&stderr_buffer) < buffer_high && - channel_not_very_much_buffered_data()) - FD_SET(connection_in, *readsetp); - /* - * Read from stdin, unless we have seen EOF or have very much - * buffered data to send to the server. - */ - if (!stdin_eof && packet_not_very_much_data_to_write()) - FD_SET(fileno(stdin), *readsetp); - - /* Select stdout/stderr if have data in buffer. */ - if (buffer_len(&stdout_buffer) > 0) - FD_SET(fileno(stdout), *writesetp); - if (buffer_len(&stderr_buffer) > 0) - FD_SET(fileno(stderr), *writesetp); - } else { - /* channel_prepare_select could have closed the last channel */ - if (session_closed && !channel_still_open() && - !packet_have_data_to_write()) { - /* clear mask since we did not call select() */ - memset(*readsetp, 0, *nallocp); - memset(*writesetp, 0, *nallocp); - return; - } else { - FD_SET(connection_in, *readsetp); - } + /* channel_prepare_select could have closed the last channel */ + if (session_closed && !channel_still_open(ssh) && + !packet_have_data_to_write()) { + /* clear mask since we did not call select() */ + memset(*readsetp, 0, *nallocp); + memset(*writesetp, 0, *nallocp); + return; } + FD_SET(connection_in, *readsetp); + /* Select server connection if have data to write to the server. */ if (packet_have_data_to_write()) FD_SET(connection_out, *writesetp); @@ -665,13 +535,13 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, */ timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */ - if (options.server_alive_interval > 0 && compat20) { + if (options.server_alive_interval > 0) { timeout_secs = options.server_alive_interval; server_alive_time = now + options.server_alive_interval; } - if (options.rekey_interval > 0 && compat20 && !rekeying) + if (options.rekey_interval > 0 && !rekeying) timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout()); - set_control_persist_exit_time(); + set_control_persist_exit_time(ssh); if (control_persist_exit_time > 0) { timeout_secs = MINIMUM(timeout_secs, control_persist_exit_time - now); @@ -730,13 +600,9 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); - /* - * Free (and clear) the buffer to reduce the amount of data that gets - * written to swap. - */ - buffer_free(bin); - buffer_free(bout); - buffer_free(berr); + sshbuf_reset(bin); + sshbuf_reset(bout); + sshbuf_reset(berr); /* Send the suspend signal to the program itself. */ kill(getpid(), SIGTSTP); @@ -744,11 +610,6 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) /* Reset window sizes in case they have changed */ received_window_change_signal = 1; - /* OK, we have been continued by the user. Reinitialize buffers. */ - buffer_init(bin); - buffer_init(bout); - buffer_init(berr); - enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); } @@ -802,7 +663,7 @@ client_process_net_input(fd_set *readset) } static void -client_status_confirm(int type, Channel *c, void *ctx) +client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx) { struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; char errmsg[256]; @@ -841,8 +702,7 @@ client_status_confirm(int type, Channel *c, void *ctx) * their stderr. */ if (tochan) { - buffer_append(&c->extended, errmsg, - strlen(errmsg)); + buffer_append(c->extended, errmsg, strlen(errmsg)); } else error("%s", errmsg); if (cr->action == CONFIRM_TTY) { @@ -853,23 +713,23 @@ client_status_confirm(int type, Channel *c, void *ctx) if (c->self == session_ident) leave_raw_mode(0); else - mux_tty_alloc_failed(c); + mux_tty_alloc_failed(ssh, c); } else if (cr->action == CONFIRM_CLOSE) { - chan_read_failed(c); - chan_write_failed(c); + chan_read_failed(ssh, c); + chan_write_failed(ssh, c); } } free(cr); } static void -client_abandon_status_confirm(Channel *c, void *ctx) +client_abandon_status_confirm(struct ssh *ssh, Channel *c, void *ctx) { free(ctx); } void -client_expect_confirm(int id, const char *request, +client_expect_confirm(struct ssh *ssh, int id, const char *request, enum confirm_action action) { struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr)); @@ -877,7 +737,7 @@ client_expect_confirm(int id, const char *request, cr->request_type = request; cr->action = action; - channel_register_status_confirm(id, client_status_confirm, + channel_register_status_confirm(ssh, id, client_status_confirm, client_abandon_status_confirm, cr); } @@ -903,7 +763,7 @@ client_register_global_confirm(global_confirm_cb *cb, void *ctx) } static void -process_cmdline(void) +process_cmdline(struct ssh *ssh) { void (*handler)(int); char *s, *cmd; @@ -966,11 +826,6 @@ process_cmdline(void) goto out; } - if (delete && !compat20) { - logit("Not supported for SSH protocol version 1."); - goto out; - } - while (isspace((u_char)*++s)) ; @@ -982,12 +837,12 @@ process_cmdline(void) goto out; } if (remote) - ok = channel_request_rforward_cancel(&fwd) == 0; + ok = channel_request_rforward_cancel(ssh, &fwd) == 0; else if (dynamic) - ok = channel_cancel_lport_listener(&fwd, + ok = channel_cancel_lport_listener(ssh, &fwd, 0, &options.fwd_opts) > 0; else - ok = channel_cancel_lport_listener(&fwd, + ok = channel_cancel_lport_listener(ssh, &fwd, CHANNEL_CANCEL_PORT_STATIC, &options.fwd_opts) > 0; if (!ok) { @@ -1001,13 +856,13 @@ process_cmdline(void) goto out; } if (local || dynamic) { - if (!channel_setup_local_fwd_listener(&fwd, + if (!channel_setup_local_fwd_listener(ssh, &fwd, &options.fwd_opts)) { logit("Port forwarding failed."); goto out; } } else { - if (channel_request_remote_forwarding(&fwd) < 0) { + if (channel_request_remote_forwarding(ssh, &fwd) < 0) { logit("Port forwarding failed."); goto out; } @@ -1027,10 +882,9 @@ process_cmdline(void) /* reasons to suppress output of an escape command in help output */ #define SUPPRESS_NEVER 0 /* never suppress, always show */ -#define SUPPRESS_PROTO1 1 /* don't show in protocol 1 sessions */ -#define SUPPRESS_MUXCLIENT 2 /* don't show in mux client sessions */ -#define SUPPRESS_MUXMASTER 4 /* don't show in mux master sessions */ -#define SUPPRESS_SYSLOG 8 /* don't show when logging to syslog */ +#define SUPPRESS_MUXCLIENT 1 /* don't show in mux client sessions */ +#define SUPPRESS_MUXMASTER 2 /* don't show in mux master sessions */ +#define SUPPRESS_SYSLOG 4 /* don't show when logging to syslog */ struct escape_help_text { const char *cmd; const char *text; @@ -1040,9 +894,9 @@ static struct escape_help_text esc_txt[] = { {".", "terminate session", SUPPRESS_MUXMASTER}, {".", "terminate connection (and any multiplexed sessions)", SUPPRESS_MUXCLIENT}, - {"B", "send a BREAK to the remote system", SUPPRESS_PROTO1}, + {"B", "send a BREAK to the remote system", SUPPRESS_NEVER}, {"C", "open a command line", SUPPRESS_MUXCLIENT}, - {"R", "request rekey", SUPPRESS_PROTO1}, + {"R", "request rekey", SUPPRESS_NEVER}, {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT}, {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT}, {"#", "list forwarded connections", SUPPRESS_NEVER}, @@ -1052,8 +906,7 @@ static struct escape_help_text esc_txt[] = { }; static void -print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client, - int using_stderr) +print_escape_help(Buffer *b, int escape_char, int mux_client, int using_stderr) { unsigned int i, suppress_flags; char string[1024]; @@ -1062,7 +915,7 @@ print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client, "Supported escape sequences:\r\n", escape_char); buffer_append(b, string, strlen(string)); - suppress_flags = (protocol2 ? 0 : SUPPRESS_PROTO1) | + suppress_flags = (mux_client ? SUPPRESS_MUXCLIENT : 0) | (mux_client ? 0 : SUPPRESS_MUXMASTER) | (using_stderr ? 0 : SUPPRESS_SYSLOG); @@ -1083,10 +936,11 @@ print_escape_help(Buffer *b, int escape_char, int protocol2, int mux_client, } /* - * Process the characters one by one, call with c==NULL for proto1 case. + * Process the characters one by one. */ static int -process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, +process_escapes(struct ssh *ssh, Channel *c, + Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) { char string[1024]; @@ -1095,19 +949,11 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, u_int i; u_char ch; char *s; - int *escape_pendingp, escape_char; - struct escape_filter_ctx *efc; + struct escape_filter_ctx *efc = c->filter_ctx == NULL ? + NULL : (struct escape_filter_ctx *)c->filter_ctx; - if (c == NULL) { - escape_pendingp = &escape_pending1; - escape_char = escape_char1; - } else { - if (c->filter_ctx == NULL) - return 0; - efc = (struct escape_filter_ctx *)c->filter_ctx; - escape_pendingp = &efc->escape_pending; - escape_char = efc->escape_char; - } + if (c->filter_ctx == NULL) + return 0; if (len <= 0) return (0); @@ -1116,27 +962,29 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, /* Get one character at a time. */ ch = buf[i]; - if (*escape_pendingp) { + if (efc->escape_pending) { /* We have previously seen an escape character. */ /* Clear the flag now. */ - *escape_pendingp = 0; + efc->escape_pending = 0; /* Process the escaped character. */ switch (ch) { case '.': /* Terminate the connection. */ snprintf(string, sizeof string, "%c.\r\n", - escape_char); + efc->escape_char); buffer_append(berr, string, strlen(string)); if (c && c->ctl_chan != -1) { - chan_read_failed(c); - chan_write_failed(c); - if (c->detach_user) - c->detach_user(c->self, NULL); + chan_read_failed(ssh, c); + chan_write_failed(ssh, c); + if (c->detach_user) { + c->detach_user(ssh, + c->self, NULL); + } c->type = SSH_CHANNEL_ABANDONED; - buffer_clear(&c->input); - chan_ibuf_empty(c); + buffer_clear(c->input); + chan_ibuf_empty(ssh, c); return 0; } else quit_pending = 1; @@ -1154,14 +1002,14 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, snprintf(string, sizeof string, "%c%s escape not available to " "multiplexed sessions\r\n", - escape_char, b); + efc->escape_char, b); buffer_append(berr, string, strlen(string)); continue; } /* Suspend the program. Inform the user */ snprintf(string, sizeof string, - "%c^Z [suspend ssh]\r\n", escape_char); + "%c^Z [suspend ssh]\r\n", efc->escape_char); buffer_append(berr, string, strlen(string)); /* Restore terminal modes and suspend. */ @@ -1171,26 +1019,20 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, continue; case 'B': - if (compat20) { - snprintf(string, sizeof string, - "%cB\r\n", escape_char); - buffer_append(berr, string, - strlen(string)); - channel_request_start(c->self, - "break", 0); - packet_put_int(1000); - packet_send(); - } + snprintf(string, sizeof string, + "%cB\r\n", efc->escape_char); + buffer_append(berr, string, strlen(string)); + channel_request_start(ssh, c->self, "break", 0); + packet_put_int(1000); + packet_send(); continue; case 'R': - if (compat20) { - if (datafellows & SSH_BUG_NOREKEY) - logit("Server does not " - "support re-keying"); - else - need_rekeying = 1; - } + if (datafellows & SSH_BUG_NOREKEY) + logit("Server does not " + "support re-keying"); + else + need_rekeying = 1; continue; case 'V': @@ -1201,7 +1043,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, if (!log_is_on_stderr()) { snprintf(string, sizeof string, "%c%c [Logging to syslog]\r\n", - escape_char, ch); + efc->escape_char, ch); buffer_append(berr, string, strlen(string)); continue; @@ -1213,7 +1055,8 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, SYSLOG_LEVEL_DEBUG3) log_change_level(++options.log_level); snprintf(string, sizeof string, - "%c%c [LogLevel %s]\r\n", escape_char, ch, + "%c%c [LogLevel %s]\r\n", + efc->escape_char, ch, log_level_name(options.log_level)); buffer_append(berr, string, strlen(string)); continue; @@ -1231,10 +1074,10 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, options.request_tty == REQUEST_TTY_FORCE); /* Stop listening for new connections. */ - channel_stop_listening(); + channel_stop_listening(ssh); snprintf(string, sizeof string, - "%c& [backgrounded]\n", escape_char); + "%c& [backgrounded]\n", efc->escape_char); buffer_append(berr, string, strlen(string)); /* Fork into background. */ @@ -1248,39 +1091,20 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, exit(0); } /* The child continues serving connections. */ - if (compat20) { - buffer_append(bin, "\004", 1); - /* fake EOF on stdin */ - return -1; - } else if (!stdin_eof) { - /* - * Sending SSH_CMSG_EOF alone does not - * always appear to be enough. So we - * try to send an EOF character first. - */ - packet_start(SSH_CMSG_STDIN_DATA); - packet_put_string("\004", 1); - packet_send(); - /* Close stdin. */ - stdin_eof = 1; - if (buffer_len(bin) == 0) { - packet_start(SSH_CMSG_EOF); - packet_send(); - } - } - continue; - + buffer_append(bin, "\004", 1); + /* fake EOF on stdin */ + return -1; case '?': - print_escape_help(berr, escape_char, compat20, + print_escape_help(berr, efc->escape_char, (c && c->ctl_chan != -1), log_is_on_stderr()); continue; case '#': snprintf(string, sizeof string, "%c#\r\n", - escape_char); + efc->escape_char); buffer_append(berr, string, strlen(string)); - s = channel_open_message(); + s = channel_open_message(ssh); buffer_append(berr, s, strlen(s)); free(s); continue; @@ -1288,12 +1112,12 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, case 'C': if (c && c->ctl_chan != -1) goto noescape; - process_cmdline(); + process_cmdline(ssh); continue; default: - if (ch != escape_char) { - buffer_put_char(bin, escape_char); + if (ch != efc->escape_char) { + buffer_put_char(bin, efc->escape_char); bytes++; } /* Escaped characters fall through here */ @@ -1304,12 +1128,12 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, * The previous character was not an escape char. * Check if this is an escape. */ - if (last_was_cr && ch == escape_char) { + if (last_was_cr && ch == efc->escape_char) { /* * It is. Set the flag and continue to * next character. */ - *escape_pendingp = 1; + efc->escape_pending = 1; continue; } } @@ -1325,115 +1149,6 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, return bytes; } -static void -client_process_input(fd_set *readset) -{ - int len; - char buf[SSH_IOBUFSZ]; - - /* Read input from stdin. */ - if (FD_ISSET(fileno(stdin), readset)) { - /* Read as much as possible. */ - len = read(fileno(stdin), buf, sizeof(buf)); - if (len < 0 && - (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) - return; /* we'll try again later */ - if (len <= 0) { - /* - * Received EOF or error. They are treated - * similarly, except that an error message is printed - * if it was an error condition. - */ - if (len < 0) { - snprintf(buf, sizeof buf, "read: %.100s\r\n", - strerror(errno)); - buffer_append(&stderr_buffer, buf, strlen(buf)); - } - /* Mark that we have seen EOF. */ - stdin_eof = 1; - /* - * Send an EOF message to the server unless there is - * data in the buffer. If there is data in the - * buffer, no message will be sent now. Code - * elsewhere will send the EOF when the buffer - * becomes empty if stdin_eof is set. - */ - if (buffer_len(&stdin_buffer) == 0) { - packet_start(SSH_CMSG_EOF); - packet_send(); - } - } else if (escape_char1 == SSH_ESCAPECHAR_NONE) { - /* - * Normal successful read, and no escape character. - * Just append the data to buffer. - */ - buffer_append(&stdin_buffer, buf, len); - } else { - /* - * Normal, successful read. But we have an escape - * character and have to process the characters one - * by one. - */ - if (process_escapes(NULL, &stdin_buffer, - &stdout_buffer, &stderr_buffer, buf, len) == -1) - return; - } - } -} - -static void -client_process_output(fd_set *writeset) -{ - int len; - char buf[100]; - - /* Write buffered output to stdout. */ - if (FD_ISSET(fileno(stdout), writeset)) { - /* Write as much data as possible. */ - len = write(fileno(stdout), buffer_ptr(&stdout_buffer), - buffer_len(&stdout_buffer)); - if (len <= 0) { - if (errno == EINTR || errno == EAGAIN || - errno == EWOULDBLOCK) - len = 0; - else { - /* - * An error or EOF was encountered. Put an - * error message to stderr buffer. - */ - snprintf(buf, sizeof buf, - "write stdout: %.50s\r\n", strerror(errno)); - buffer_append(&stderr_buffer, buf, strlen(buf)); - quit_pending = 1; - return; - } - } - /* Consume printed data from the buffer. */ - buffer_consume(&stdout_buffer, len); - } - /* Write buffered output to stderr. */ - if (FD_ISSET(fileno(stderr), writeset)) { - /* Write as much data as possible. */ - len = write(fileno(stderr), buffer_ptr(&stderr_buffer), - buffer_len(&stderr_buffer)); - if (len <= 0) { - if (errno == EINTR || errno == EAGAIN || - errno == EWOULDBLOCK) - len = 0; - else { - /* - * EOF or error, but can't even print - * error message. - */ - quit_pending = 1; - return; - } - } - /* Consume printed characters from the buffer. */ - buffer_consume(&stderr_buffer, len); - } -} - /* * Get packets from the connection input buffer, and process them as long as * there are packets available. @@ -1449,7 +1164,7 @@ client_process_output(fd_set *writeset) static void client_process_buffered_input_packets(void) { - dispatch_run(DISPATCH_NONBLOCK, &quit_pending, active_state); + ssh_dispatch_run_fatal(active_state, DISPATCH_NONBLOCK, &quit_pending); } /* scan buf[] for '~' before sending data to the peer */ @@ -1468,25 +1183,25 @@ client_new_escape_filter_ctx(int escape_char) /* Free the escape filter context on channel free */ void -client_filter_cleanup(int cid, void *ctx) +client_filter_cleanup(struct ssh *ssh, int cid, void *ctx) { free(ctx); } int -client_simple_escape_filter(Channel *c, char *buf, int len) +client_simple_escape_filter(struct ssh *ssh, Channel *c, char *buf, int len) { if (c->extended_usage != CHAN_EXTENDED_WRITE) return 0; - return process_escapes(c, &c->input, &c->output, &c->extended, + return process_escapes(ssh, c, c->input, c->output, c->extended, buf, len); } static void -client_channel_closed(int id, void *arg) +client_channel_closed(struct ssh *ssh, int id, void *arg) { - channel_cancel_cleanup(id); + channel_cancel_cleanup(ssh, id); session_closed = 1; leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); } @@ -1497,9 +1212,9 @@ client_channel_closed(int id, void *arg) * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character * used as an escape character for terminating or suspending the session. */ - int -client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) +client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, + int ssh2_chan_id) { fd_set *readset = NULL, *writeset = NULL; double start_time, total_time; @@ -1537,40 +1252,22 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) } else { debug("pledge: network"); - if (pledge("stdio unix inet dns tty", NULL) == -1) + if (pledge("stdio unix inet dns proc tty", NULL) == -1) fatal("%s pledge(): %s", __func__, strerror(errno)); } start_time = get_current_time(); /* Initialize variables. */ - escape_pending1 = 0; last_was_cr = 1; exit_status = -1; - stdin_eof = 0; - buffer_high = 64 * 1024; connection_in = packet_get_connection_in(); connection_out = packet_get_connection_out(); max_fd = MAXIMUM(connection_in, connection_out); - if (!compat20) { - /* enable nonblocking unless tty */ - if (!isatty(fileno(stdin))) - set_nonblock(fileno(stdin)); - if (!isatty(fileno(stdout))) - set_nonblock(fileno(stdout)); - if (!isatty(fileno(stderr))) - set_nonblock(fileno(stderr)); - max_fd = MAXIMUM(max_fd, fileno(stdin)); - max_fd = MAXIMUM(max_fd, fileno(stdout)); - max_fd = MAXIMUM(max_fd, fileno(stderr)); - } quit_pending = 0; - escape_char1 = escape_char_arg; /* Initialize buffers. */ - buffer_init(&stdin_buffer); - buffer_init(&stdout_buffer); buffer_init(&stderr_buffer); client_init_dispatch(); @@ -1592,22 +1289,17 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) if (have_pty) enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); - if (compat20) { - session_ident = ssh2_chan_id; - if (session_ident != -1) { - if (escape_char_arg != SSH_ESCAPECHAR_NONE) { - channel_register_filter(session_ident, - client_simple_escape_filter, NULL, - client_filter_cleanup, - client_new_escape_filter_ctx( - escape_char_arg)); - } - channel_register_cleanup(session_ident, - client_channel_closed, 0); + session_ident = ssh2_chan_id; + if (session_ident != -1) { + if (escape_char_arg != SSH_ESCAPECHAR_NONE) { + channel_register_filter(ssh, session_ident, + client_simple_escape_filter, NULL, + client_filter_cleanup, + client_new_escape_filter_ctx( + escape_char_arg)); } - } else { - /* Check if we should immediately send eof on stdin. */ - client_check_initial_eof_on_stdin(); + channel_register_cleanup(ssh, session_ident, + client_channel_closed, 0); } /* Main loop of the client for the interactive session mode. */ @@ -1616,38 +1308,31 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) /* Process buffered packets sent by the server. */ client_process_buffered_input_packets(); - if (compat20 && session_closed && !channel_still_open()) + if (session_closed && !channel_still_open(ssh)) break; - if (ssh_packet_is_rekeying(active_state)) { + if (ssh_packet_is_rekeying(ssh)) { debug("rekeying in progress"); } else if (need_rekeying) { /* manual rekey request */ debug("need rekeying"); - if ((r = kex_start_rekex(active_state)) != 0) + if ((r = kex_start_rekex(ssh)) != 0) fatal("%s: kex_start_rekex: %s", __func__, ssh_err(r)); need_rekeying = 0; } else { - /* - * Make packets of buffered stdin data, and buffer - * them for sending to the server. - */ - if (!compat20) - client_make_packets_from_stdin_data(); - /* * Make packets from buffered channel data, and * enqueue them for sending to the server. */ if (packet_not_very_much_data_to_write()) - channel_output_poll(); + channel_output_poll(ssh); /* * Check if the window size has changed, and buffer a * message about it to the server if so. */ - client_check_window_change(); + client_check_window_change(ssh); if (quit_pending) break; @@ -1657,15 +1342,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) * available on one of the descriptors). */ max_fd2 = max_fd; - client_wait_until_can_do_something(&readset, &writeset, - &max_fd2, &nalloc, ssh_packet_is_rekeying(active_state)); + client_wait_until_can_do_something(ssh, &readset, &writeset, + &max_fd2, &nalloc, ssh_packet_is_rekeying(ssh)); if (quit_pending) break; /* Do channel operations unless rekeying in progress. */ - if (!ssh_packet_is_rekeying(active_state)) - channel_after_select(readset, writeset); + if (!ssh_packet_is_rekeying(ssh)) + channel_after_select(ssh, readset, writeset); /* Buffer input from the connection. */ client_process_net_input(readset); @@ -1673,16 +1358,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) if (quit_pending) break; - if (!compat20) { - /* Buffer data from stdin */ - client_process_input(readset); - /* - * Process output to stdout and stderr. Output to - * the connection is processed elsewhere (above). - */ - client_process_output(writeset); - } - /* * Send as much buffered packet data as possible to the * sender. @@ -1710,16 +1385,14 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) /* Stop watching for window change. */ signal(SIGWINCH, SIG_DFL); - if (compat20) { - packet_start(SSH2_MSG_DISCONNECT); - packet_put_int(SSH2_DISCONNECT_BY_APPLICATION); - packet_put_cstring("disconnected by user"); - packet_put_cstring(""); /* language tag */ - packet_send(); - packet_write_wait(); - } + packet_start(SSH2_MSG_DISCONNECT); + packet_put_int(SSH2_DISCONNECT_BY_APPLICATION); + packet_put_cstring("disconnected by user"); + packet_put_cstring(""); /* language tag */ + packet_send(); + packet_write_wait(); - channel_free_all(); + channel_free_all(ssh); if (have_pty) leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); @@ -1742,8 +1415,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) exit_status = 0; } - if (received_signal) - fatal("Killed by signal %d.", (int) received_signal); + if (received_signal) { + verbose("Killed by signal %d.", (int) received_signal); + cleanup_exit(0); + } /* * In interactive mode (with pseudo tty) display a message indicating @@ -1755,16 +1430,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) buffer_append(&stderr_buffer, buf, strlen(buf)); } - /* Output any buffered data for stdout. */ - if (buffer_len(&stdout_buffer) > 0) { - len = atomicio(vwrite, fileno(stdout), - buffer_ptr(&stdout_buffer), buffer_len(&stdout_buffer)); - if (len < 0 || (u_int)len != buffer_len(&stdout_buffer)) - error("Write failed flushing stdout buffer."); - else - buffer_consume(&stdout_buffer, len); - } - /* Output any buffered data for stderr. */ if (buffer_len(&stderr_buffer) > 0) { len = atomicio(vwrite, fileno(stderr), @@ -1777,8 +1442,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) /* Clear and free any buffers. */ explicit_bzero(buf, sizeof(buf)); - buffer_free(&stdin_buffer); - buffer_free(&stdout_buffer); buffer_free(&stderr_buffer); /* Report bytes transferred, and transfer rates. */ @@ -1796,95 +1459,9 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) /*********/ -static int -client_input_stdout_data(int type, u_int32_t seq, void *ctxt) -{ - u_int data_len; - char *data = packet_get_string(&data_len); - packet_check_eom(); - buffer_append(&stdout_buffer, data, data_len); - explicit_bzero(data, data_len); - free(data); - return 0; -} -static int -client_input_stderr_data(int type, u_int32_t seq, void *ctxt) -{ - u_int data_len; - char *data = packet_get_string(&data_len); - packet_check_eom(); - buffer_append(&stderr_buffer, data, data_len); - explicit_bzero(data, data_len); - free(data); - return 0; -} -static int -client_input_exit_status(int type, u_int32_t seq, void *ctxt) -{ - exit_status = packet_get_int(); - packet_check_eom(); - /* Acknowledge the exit. */ - packet_start(SSH_CMSG_EXIT_CONFIRMATION); - packet_send(); - /* - * Must wait for packet to be sent since we are - * exiting the loop. - */ - packet_write_wait(); - /* Flag that we want to exit. */ - quit_pending = 1; - return 0; -} - -static int -client_input_agent_open(int type, u_int32_t seq, void *ctxt) -{ - Channel *c = NULL; - int r, remote_id, sock; - - /* Read the remote channel number from the message. */ - remote_id = packet_get_int(); - packet_check_eom(); - - /* - * Get a connection to the local authentication agent (this may again - * get forwarded). - */ - if ((r = ssh_get_authentication_socket(&sock)) != 0 && - r != SSH_ERR_AGENT_NOT_PRESENT) - debug("%s: ssh_get_authentication_socket: %s", - __func__, ssh_err(r)); - - - /* - * If we could not connect the agent, send an error message back to - * the server. This should never happen unless the agent dies, - * because authentication forwarding is only enabled if we have an - * agent. - */ - if (sock >= 0) { - c = channel_new("", SSH_CHANNEL_OPEN, sock, sock, - -1, 0, 0, 0, "authentication agent connection", 1); - c->remote_id = remote_id; - c->force_drain = 1; - } - if (c == NULL) { - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(remote_id); - } else { - /* Send a confirmation to the remote host. */ - debug("Forwarding authentication connection."); - packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(remote_id); - packet_put_int(c->self); - } - packet_send(); - return 0; -} - static Channel * -client_request_forwarded_tcpip(const char *request_type, int rchan, - u_int rwindow, u_int rmaxpack) +client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type, + int rchan, u_int rwindow, u_int rmaxpack) { Channel *c = NULL; struct sshbuf *b = NULL; @@ -1902,7 +1479,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan, debug("%s: listen %s port %d, originator %s port %d", __func__, listen_address, listen_port, originator_address, originator_port); - c = channel_connect_by_listen_address(listen_address, listen_port, + c = channel_connect_by_listen_address(ssh, listen_address, listen_port, "forwarded-tcpip", originator_address); if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { @@ -1921,7 +1498,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan, (r = sshbuf_put_u32(b, listen_port)) != 0 || (r = sshbuf_put_cstring(b, originator_address)) != 0 || (r = sshbuf_put_u32(b, originator_port)) != 0 || - (r = sshbuf_put_stringb(&c->output, b)) != 0) { + (r = sshbuf_put_stringb(c->output, b)) != 0) { error("%s: compose for muxclient %s", __func__, ssh_err(r)); goto out; @@ -1936,7 +1513,8 @@ client_request_forwarded_tcpip(const char *request_type, int rchan, } static Channel * -client_request_forwarded_streamlocal(const char *request_type, int rchan) +client_request_forwarded_streamlocal(struct ssh *ssh, + const char *request_type, int rchan) { Channel *c = NULL; char *listen_path; @@ -1950,14 +1528,14 @@ client_request_forwarded_streamlocal(const char *request_type, int rchan) debug("%s: %s", __func__, listen_path); - c = channel_connect_by_listen_path(listen_path, + c = channel_connect_by_listen_path(ssh, listen_path, "forwarded-streamlocal@openssh.com", "forwarded-streamlocal"); free(listen_path); return c; } static Channel * -client_request_x11(const char *request_type, int rchan) +client_request_x11(struct ssh *ssh, const char *request_type, int rchan) { Channel *c = NULL; char *originator; @@ -1987,10 +1565,10 @@ client_request_x11(const char *request_type, int rchan) debug("client_request_x11: request from %s %d", originator, originator_port); free(originator); - sock = x11_connect_display(); + sock = x11_connect_display(ssh); if (sock < 0) return NULL; - c = channel_new("x11", + c = channel_new(ssh, "x11", SSH_CHANNEL_X11_OPEN, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); c->force_drain = 1; @@ -1998,7 +1576,7 @@ client_request_x11(const char *request_type, int rchan) } static Channel * -client_request_agent(const char *request_type, int rchan) +client_request_agent(struct ssh *ssh, const char *request_type, int rchan) { Channel *c = NULL; int r, sock; @@ -2015,7 +1593,7 @@ client_request_agent(const char *request_type, int rchan) __func__, ssh_err(r)); return NULL; } - c = channel_new("authentication agent connection", + c = channel_new(ssh, "authentication agent connection", SSH_CHANNEL_OPEN, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "authentication agent connection", 1); @@ -2024,7 +1602,8 @@ client_request_agent(const char *request_type, int rchan) } int -client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) +client_request_tun_fwd(struct ssh *ssh, int tun_mode, + int local_tun, int remote_tun) { Channel *c; int fd; @@ -2032,11 +1611,6 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) if (tun_mode == SSH_TUNMODE_NO) return 0; - if (!compat20) { - error("Tunnel forwarding is not supported for protocol 1"); - return -1; - } - debug("Requesting tun unit %d in mode %d", local_tun, tun_mode); /* Open local tunnel device */ @@ -2045,13 +1619,13 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) return -1; } - c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, + c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); c->datagram = 1; #if defined(SSH_TUN_FILTER) if (options.tun_open == SSH_TUNMODE_POINTOPOINT) - channel_register_filter(c->self, sys_tun_infilter, + channel_register_filter(ssh, c->self, sys_tun_infilter, sys_tun_outfilter, NULL, NULL); #endif @@ -2069,7 +1643,7 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) /* XXXX move to generic input handler */ static int -client_input_channel_open(int type, u_int32_t seq, void *ctxt) +client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = NULL; char *ctype; @@ -2085,20 +1659,21 @@ client_input_channel_open(int type, u_int32_t seq, void *ctxt) ctype, rchan, rwindow, rmaxpack); if (strcmp(ctype, "forwarded-tcpip") == 0) { - c = client_request_forwarded_tcpip(ctype, rchan, rwindow, + c = client_request_forwarded_tcpip(ssh, ctype, rchan, rwindow, rmaxpack); } else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) { - c = client_request_forwarded_streamlocal(ctype, rchan); + c = client_request_forwarded_streamlocal(ssh, ctype, rchan); } else if (strcmp(ctype, "x11") == 0) { - c = client_request_x11(ctype, rchan); + c = client_request_x11(ssh, ctype, rchan); } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { - c = client_request_agent(ctype, rchan); + c = client_request_agent(ssh, ctype, rchan); } if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { debug3("proxied to downstream: %s", ctype); } else if (c != NULL) { debug("confirm %s", ctype); c->remote_id = rchan; + c->have_remote_id = 1; c->remote_window = rwindow; c->remote_maxpacket = rmaxpack; if (c->type != SSH_CHANNEL_CONNECTING) { @@ -2125,15 +1700,15 @@ client_input_channel_open(int type, u_int32_t seq, void *ctxt) } static int -client_input_channel_req(int type, u_int32_t seq, void *ctxt) +client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = NULL; int exitval, id, reply, success = 0; char *rtype; id = packet_get_int(); - c = channel_lookup(id); - if (channel_proxy_upstream(c, type, seq, ctxt)) + c = channel_lookup(ssh, id); + if (channel_proxy_upstream(c, type, seq, ssh)) return 0; rtype = packet_get_string(NULL); reply = packet_get_char(); @@ -2148,11 +1723,11 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt) "unknown channel", id); } else if (strcmp(rtype, "eow@openssh.com") == 0) { packet_check_eom(); - chan_rcvd_eow(c); + chan_rcvd_eow(ssh, c); } else if (strcmp(rtype, "exit-status") == 0) { exitval = packet_get_int(); if (c->ctl_chan != -1) { - mux_exit_message(c, exitval); + mux_exit_message(ssh, c, exitval); success = 1; } else if (id == session_ident) { /* Record exit value of local session */ @@ -2166,6 +1741,9 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt) packet_check_eom(); } if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) { + if (!c->have_remote_id) + fatal("%s: channel %d: no remote_id", + __func__, c->self); packet_start(success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); packet_put_int(c->remote_id); @@ -2187,9 +1765,7 @@ struct hostkeys_update_ctx { */ struct sshkey **keys; int *keys_seen; - size_t nkeys; - - size_t nnew; + size_t nkeys, nnew; /* * Keys that are in known_hosts, but were not present in the update @@ -2226,8 +1802,7 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx) size_t i; struct sshkey **tmp; - if (l->status != HKF_STATUS_MATCHED || l->key == NULL || - l->key->type == KEY_RSA1) + if (l->status != HKF_STATUS_MATCHED || l->key == NULL) return 0; /* Mark off keys we've already seen for this host */ @@ -2242,9 +1817,9 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx) /* This line contained a key that not offered by the server */ debug3("%s: deprecated %s key at %s:%ld", __func__, sshkey_ssh_name(l->key), l->path, l->linenum); - if ((tmp = reallocarray(ctx->old_keys, ctx->nold + 1, + if ((tmp = recallocarray(ctx->old_keys, ctx->nold, ctx->nold + 1, sizeof(*ctx->old_keys))) == NULL) - fatal("%s: reallocarray failed nold = %zu", + fatal("%s: recallocarray failed nold = %zu", __func__, ctx->nold); ctx->old_keys = tmp; ctx->old_keys[ctx->nold++] = l->key; @@ -2323,9 +1898,9 @@ update_known_hosts(struct hostkeys_update_ctx *ctx) } static void -client_global_hostkeys_private_confirm(int type, u_int32_t seq, void *_ctx) +client_global_hostkeys_private_confirm(struct ssh *ssh, int type, + u_int32_t seq, void *_ctx) { - struct ssh *ssh = active_state; /* XXX */ struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; size_t i, ndone; struct sshbuf *signdata; @@ -2476,9 +2051,9 @@ client_input_hostkeys(void) } } /* Key is good, record it */ - if ((tmp = reallocarray(ctx->keys, ctx->nkeys + 1, + if ((tmp = recallocarray(ctx->keys, ctx->nkeys, ctx->nkeys + 1, sizeof(*ctx->keys))) == NULL) - fatal("%s: reallocarray failed nkeys = %zu", + fatal("%s: recallocarray failed nkeys = %zu", __func__, ctx->nkeys); ctx->keys = tmp; ctx->keys[ctx->nkeys++] = key; @@ -2566,7 +2141,7 @@ client_input_hostkeys(void) } static int -client_input_global_request(int type, u_int32_t seq, void *ctxt) +client_input_global_request(int type, u_int32_t seq, struct ssh *ssh) { char *rtype; int want_reply; @@ -2589,7 +2164,7 @@ client_input_global_request(int type, u_int32_t seq, void *ctxt) } void -client_session2_setup(int id, int want_tty, int want_subsystem, +client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env) { int len; @@ -2597,8 +2172,8 @@ client_session2_setup(int id, int want_tty, int want_subsystem, debug2("%s: id %d", __func__, id); - if ((c = channel_lookup(id)) == NULL) - fatal("client_session2_setup: channel %d: unknown channel", id); + if ((c = channel_lookup(ssh, id)) == NULL) + fatal("%s: channel %d: unknown channel", __func__, id); packet_set_interactive(want_tty, options.ip_qos_interactive, options.ip_qos_bulk); @@ -2610,8 +2185,8 @@ client_session2_setup(int id, int want_tty, int want_subsystem, if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0) memset(&ws, 0, sizeof(ws)); - channel_request_start(id, "pty-req", 1); - client_expect_confirm(id, "PTY allocation", CONFIRM_TTY); + channel_request_start(ssh, id, "pty-req", 1); + client_expect_confirm(ssh, id, "PTY allocation", CONFIRM_TTY); packet_put_cstring(term != NULL ? term : ""); packet_put_int((u_int)ws.ws_col); packet_put_int((u_int)ws.ws_row); @@ -2654,7 +2229,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem, } debug("Sending env %s = %s", name, val); - channel_request_start(id, "env", 0); + channel_request_start(ssh, id, "env", 0); packet_put_cstring(name); packet_put_cstring(val); packet_send(); @@ -2669,25 +2244,26 @@ client_session2_setup(int id, int want_tty, int want_subsystem, if (want_subsystem) { debug("Sending subsystem: %.*s", len, (u_char*)buffer_ptr(cmd)); - channel_request_start(id, "subsystem", 1); - client_expect_confirm(id, "subsystem", CONFIRM_CLOSE); + channel_request_start(ssh, id, "subsystem", 1); + client_expect_confirm(ssh, id, "subsystem", + CONFIRM_CLOSE); } else { debug("Sending command: %.*s", len, (u_char*)buffer_ptr(cmd)); - channel_request_start(id, "exec", 1); - client_expect_confirm(id, "exec", CONFIRM_CLOSE); + channel_request_start(ssh, id, "exec", 1); + client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE); } packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); packet_send(); } else { - channel_request_start(id, "shell", 1); - client_expect_confirm(id, "shell", CONFIRM_CLOSE); + channel_request_start(ssh, id, "shell", 1); + client_expect_confirm(ssh, id, "shell", CONFIRM_CLOSE); packet_send(); } } static void -client_init_dispatch_20(void) +client_init_dispatch(void) { dispatch_init(&dispatch_protocol_error); @@ -2712,45 +2288,6 @@ client_init_dispatch_20(void) dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); } -static void -client_init_dispatch_13(void) -{ - dispatch_init(NULL); - dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close); - dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation); - dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data); - dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); - dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); - dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open); - dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status); - dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data); - dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data); - - dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ? - &client_input_agent_open : &deny_input_open); - dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ? - &x11_input_open : &deny_input_open); -} - -static void -client_init_dispatch_15(void) -{ - client_init_dispatch_13(); - dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); - dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose); -} - -static void -client_init_dispatch(void) -{ - if (compat20) - client_init_dispatch_20(); - else if (compat13) - client_init_dispatch_13(); - else - client_init_dispatch_15(); -} - void client_stop_mux(void) { diff --git a/clientloop.h b/clientloop.h index ae83aa8cf427..a1975ccc8a16 100644 --- a/clientloop.h +++ b/clientloop.h @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.h,v 1.33 2016/09/30 09:19:13 markus Exp $ */ +/* $OpenBSD: clientloop.h,v 1.34 2017/09/12 06:32:07 djm Exp $ */ /* * Author: Tatu Ylonen @@ -37,28 +37,31 @@ #include +struct ssh; + /* Client side main loop for the interactive session. */ -int client_loop(int, int, int); -int client_x11_get_proto(const char *, const char *, u_int, u_int, - char **, char **); +int client_loop(struct ssh *, int, int, int); +int client_x11_get_proto(struct ssh *, const char *, const char *, + u_int, u_int, char **, char **); void client_global_request_reply_fwd(int, u_int32_t, void *); -void client_session2_setup(int, int, int, const char *, struct termios *, - int, Buffer *, char **); -int client_request_tun_fwd(int, int, int); +void client_session2_setup(struct ssh *, int, int, int, + const char *, struct termios *, int, Buffer *, char **); +int client_request_tun_fwd(struct ssh *, int, int, int); void client_stop_mux(void); /* Escape filter for protocol 2 sessions */ void *client_new_escape_filter_ctx(int); -void client_filter_cleanup(int, void *); -int client_simple_escape_filter(Channel *, char *, int); +void client_filter_cleanup(struct ssh *, int, void *); +int client_simple_escape_filter(struct ssh *, Channel *, char *, int); /* Global request confirmation callbacks */ -typedef void global_confirm_cb(int, u_int32_t seq, void *); +typedef void global_confirm_cb(struct ssh *, int, u_int32_t, void *); void client_register_global_confirm(global_confirm_cb *, void *); /* Channel request confirmation callbacks */ enum confirm_action { CONFIRM_WARN = 0, CONFIRM_CLOSE, CONFIRM_TTY }; -void client_expect_confirm(int, const char *, enum confirm_action); +void client_expect_confirm(struct ssh *, int, const char *, + enum confirm_action); /* Multiplexing protocol version */ #define SSHMUX_VER 4 @@ -73,8 +76,8 @@ void client_expect_confirm(int, const char *, enum confirm_action); #define SSHMUX_COMMAND_CANCEL_FWD 7 /* Cancel forwarding(s) */ #define SSHMUX_COMMAND_PROXY 8 /* Open new connection */ -void muxserver_listen(void); +void muxserver_listen(struct ssh *); int muxclient(const char *); -void mux_exit_message(Channel *, int); -void mux_tty_alloc_failed(Channel *); +void mux_exit_message(struct ssh *, Channel *, int); +void mux_tty_alloc_failed(struct ssh *ssh, Channel *); diff --git a/compat.c b/compat.c index 1e80cfa9a73a..d82135e2b5e0 100644 --- a/compat.c +++ b/compat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: compat.c,v 1.100 2017/02/03 23:01:19 djm Exp $ */ +/* $OpenBSD: compat.c,v 1.104 2017/07/25 09:22:25 dtucker Exp $ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * @@ -39,24 +39,8 @@ #include "match.h" #include "kex.h" -int compat13 = 0; -int compat20 = 0; int datafellows = 0; -void -enable_compat20(void) -{ - if (compat20) - return; - debug("Enabling compatibility mode for protocol 2.0"); - compat20 = 1; -} -void -enable_compat13(void) -{ - debug("Enabling compatibility mode for protocol 1.3"); - compat13 = 1; -} /* datafellows bug compatibility */ u_int compat_datafellows(const char *version) @@ -193,9 +177,12 @@ compat_datafellows(const char *version) "TTSSH/2.72*", SSH_BUG_HOSTKEYS }, { "WinSCP_release_4*," "WinSCP_release_5.0*," - "WinSCP_release_5.1*," - "WinSCP_release_5.5*," - "WinSCP_release_5.6*," + "WinSCP_release_5.1," + "WinSCP_release_5.1.*," + "WinSCP_release_5.5," + "WinSCP_release_5.5.*," + "WinSCP_release_5.6," + "WinSCP_release_5.6.*," "WinSCP_release_5.7," "WinSCP_release_5.7.1," "WinSCP_release_5.7.2," @@ -232,13 +219,6 @@ proto_spec(const char *spec) return ret; for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) { switch (atoi(p)) { - case 1: -#ifdef WITH_SSH1 - if (ret == SSH_PROTO_UNKNOWN) - ret |= SSH_PROTO_1_PREFERRED; - ret |= SSH_PROTO_1; -#endif - break; case 2: ret |= SSH_PROTO_2; break; diff --git a/compat.h b/compat.h index 2be290a8a8fe..2e7830f1bc8c 100644 --- a/compat.h +++ b/compat.h @@ -1,4 +1,4 @@ -/* $OpenBSD: compat.h,v 1.48 2015/05/26 23:23:40 dtucker Exp $ */ +/* $OpenBSD: compat.h,v 1.49 2017/04/30 23:13:25 djm Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. @@ -63,15 +63,11 @@ #define SSH_BUG_HOSTKEYS 0x20000000 #define SSH_BUG_DHGEX_LARGE 0x40000000 -void enable_compat13(void); -void enable_compat20(void); u_int compat_datafellows(const char *); int proto_spec(const char *); char *compat_cipher_proposal(char *); char *compat_pkalg_proposal(char *); char *compat_kex_proposal(char *); -extern int compat13; -extern int compat20; extern int datafellows; #endif diff --git a/config.h.in b/config.h.in index b65420e4a9dc..63fc548b5843 100644 --- a/config.h.in +++ b/config.h.in @@ -252,6 +252,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_BSTRING_H +/* calloc(x, 0) returns NULL */ +#undef HAVE_CALLOC + /* Define to 1 if you have the `cap_rights_limit' function. */ #undef HAVE_CAP_RIGHTS_LIMIT @@ -469,6 +472,9 @@ /* Define to 1 if you have the `freeaddrinfo' function. */ #undef HAVE_FREEADDRINFO +/* Define to 1 if you have the `freezero' function. */ +#undef HAVE_FREEZERO + /* Define to 1 if the system has the type `fsblkcnt_t'. */ #undef HAVE_FSBLKCNT_T @@ -769,6 +775,10 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MAILLOCK_H +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + /* Define to 1 if you have the `mblen' function. */ #undef HAVE_MBLEN @@ -899,12 +909,19 @@ /* Define to 1 if you have the header file. */ #undef HAVE_READPASSPHRASE_H +/* Define to 1 if your system has a GNU libc compatible `realloc' function, + and to 0 otherwise. */ +#undef HAVE_REALLOC + /* Define to 1 if you have the `reallocarray' function. */ #undef HAVE_REALLOCARRAY /* Define to 1 if you have the `realpath' function. */ #undef HAVE_REALPATH +/* Define to 1 if you have the `recallocarray' function. */ +#undef HAVE_RECALLOCARRAY + /* Define to 1 if you have the `recvmsg' function. */ #undef HAVE_RECVMSG @@ -1115,6 +1132,9 @@ /* Define to 1 if you have the `strsep' function. */ #undef HAVE_STRSEP +/* Define to 1 if you have the `strsignal' function. */ +#undef HAVE_STRSIGNAL + /* Define to 1 if you have the `strtoll' function. */ #undef HAVE_STRTOLL @@ -1157,6 +1177,12 @@ /* Define to 1 if `st_blksize' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_BLKSIZE +/* Define to 1 if `st_mtim' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_MTIM + +/* Define to 1 if `st_mtime' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_MTIME + /* Define to 1 if the system has the type `struct timespec'. */ #undef HAVE_STRUCT_TIMESPEC @@ -1181,8 +1207,8 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_BSDTTY_H -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_CAPABILITY_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_CAPSICUM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_CDEFS_H @@ -1719,9 +1745,6 @@ /* Define if you want SELinux support. */ #undef WITH_SELINUX -/* include SSH protocol version 1 support */ -#undef WITH_SSH1 - /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD @@ -1760,11 +1783,20 @@ /* Define if we don't have struct __res_state in resolv.h */ #undef __res_state +/* Define to rpl_calloc if the replacement function should be used. */ +#undef calloc + /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc + +/* Define to rpl_realloc if the replacement function should be used. */ +#undef realloc + /* type to use in place of socklen_t if not defined */ #undef socklen_t diff --git a/configure b/configure index 5eaaa392f099..b2c2c3b91745 100755 --- a/configure +++ b/configure @@ -624,7 +624,6 @@ ac_includes_default="\ #endif" ac_subst_vars='LTLIBOBJS -LIBOBJS UNSUPPORTED_ALGORITHMS TEST_MALLOC_OPTIONS TEST_SSH_UTF8 @@ -648,7 +647,7 @@ TEST_SSH_ECC LIBEDIT PKGCONFIG LDNSCONFIG -COMMENT_OUT_RSA1 +LIBOBJS LD PATH_PASSWD_PROG STARTUP_SCRIPT_SHELL @@ -735,13 +734,14 @@ ac_user_opts=' enable_option_checking enable_largefile with_openssl -with_ssh1 with_stackprotect with_hardening with_rpath with_cflags +with_cflags_after with_cppflags with_ldflags +with_ldflags_after with_libs with_Werror with_solaris_contracts @@ -1430,13 +1430,14 @@ Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --without-openssl Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL** - --with-ssh1 Enable support for SSH protocol 1 --without-stackprotect Don't use compiler's stack protection --without-hardening Don't use toolchain hardening flags --without-rpath Disable auto-added -R linker paths --with-cflags Specify additional flags to pass to compiler + --with-cflags-after Specify additional flags to pass to compiler after configure --with-cppflags Specify additional flags to pass to preprocessor --with-ldflags Specify additional flags to pass to linker + --with-ldflags-after Specify additional flags to pass to linker after configure --with-libs Specify additional libraries to link with --with-Werror Build main code with -Werror --with-solaris-contracts Enable Solaris process contracts (experimental) @@ -5634,14 +5635,11 @@ fi openssl=yes -ssh1=no -COMMENT_OUT_RSA1="#no ssh1#" # Check whether --with-openssl was given. if test "${with_openssl+set}" = set; then : withval=$with_openssl; if test "x$withval" = "xno" ; then openssl=no - ssh1=no fi @@ -5657,41 +5655,6 @@ cat >>confdefs.h <<_ACEOF #define WITH_OPENSSL 1 _ACEOF -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -# Check whether --with-ssh1 was given. -if test "${with_ssh1+set}" = set; then : - withval=$with_ssh1; - if test "x$withval" = "xyes" ; then - if test "x$openssl" = "xno" ; then - as_fn_error $? "Cannot enable SSH protocol 1 with OpenSSL disabled" "$LINENO" 5 - fi - ssh1=yes - COMMENT_OUT_RSA1="" - elif test "x$withval" = "xno" ; then - ssh1=no - else - as_fn_error $? "unknown --with-ssh1 argument" "$LINENO" 5 - fi - - -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether SSH protocol 1 support is enabled" >&5 -$as_echo_n "checking whether SSH protocol 1 support is enabled... " >&6; } -if test "x$ssh1" = "xyes" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - -cat >>confdefs.h <<_ACEOF -#define WITH_SSH1 1 -_ACEOF - - else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } @@ -5742,6 +5705,49 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$saved_CFLAGS" if test "$GCC" = "yes" || test "$GCC" = "egcs"; then + { + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -pipe" >&5 +$as_echo_n "checking if $CC supports compile flag -pipe... " >&6; } + saved_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $WERROR -pipe" + _define_flag="" + test "x$_define_flag" = "x" && _define_flag="-pipe" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int main(int argc, char **argv) { + /* Some math to catch -ftrapv problems in the toolchain */ + int i = 123 * argc, j = 456 + argc, k = 789 - argc; + float l = i * 2.1; + double m = l / 0.5; + long long int n = argc * 12345LL, o = 12345LL * (long long int)argc; + printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); + exit(0); +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +if `grep -i "unrecognized option" conftest.err >/dev/null` +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + CFLAGS="$saved_CFLAGS" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$saved_CFLAGS $_define_flag" +fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + CFLAGS="$saved_CFLAGS" + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +} { { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Qunused-arguments" >&5 $as_echo_n "checking if $CC supports compile flag -Qunused-arguments... " >&6; } @@ -6215,6 +6221,7 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } + if test "x$use_toolchain_hardening" = "x1"; then { { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -D_FORTIFY_SOURCE=2" >&5 $as_echo_n "checking if $CC supports compile flag -D_FORTIFY_SOURCE=2... " >&6; } @@ -6258,7 +6265,6 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext } - if test "x$use_toolchain_hardening" = "x1"; then { { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,relro" >&5 $as_echo_n "checking if $LD supports link flag -Wl,-z,relro... " >&6; } @@ -6620,6 +6626,19 @@ if test "${with_cflags+set}" = set; then : fi + +# Check whether --with-cflags-after was given. +if test "${with_cflags_after+set}" = set; then : + withval=$with_cflags_after; + if test -n "$withval" && test "x$withval" != "xno" && \ + test "x${withval}" != "xyes"; then + CFLAGS_AFTER="$withval" + fi + + +fi + + # Check whether --with-cppflags was given. if test "${with_cppflags+set}" = set; then : withval=$with_cppflags; @@ -6644,6 +6663,18 @@ if test "${with_ldflags+set}" = set; then : fi +# Check whether --with-ldflags-after was given. +if test "${with_ldflags_after+set}" = set; then : + withval=$with_ldflags_after; + if test -n "$withval" && test "x$withval" != "xno" && \ + test "x${withval}" != "xyes"; then + LDFLAGS_AFTER="$withval" + fi + + +fi + + # Check whether --with-libs was given. if test "${with_libs+set}" = set; then : withval=$with_libs; @@ -6712,7 +6743,6 @@ for ac_header in \ sys/audit.h \ sys/bitypes.h \ sys/bsdtty.h \ - sys/capability.h \ sys/cdefs.h \ sys/dir.h \ sys/mman.h \ @@ -6756,6 +6786,25 @@ fi done +# sys/capsicum.h requires sys/types.h +for ac_header in sys/capsicum.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/capsicum.h" "ac_cv_header_sys_capsicum_h" " +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +" +if test "x$ac_cv_header_sys_capsicum_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_CAPSICUM_H 1 +_ACEOF + +fi + +done + + # lastlog.h requires sys/time.h to be included first on Solaris for ac_header in lastlog.h do : @@ -8208,6 +8257,8 @@ $as_echo "#define UNIXWARE_LONG_PASSWORDS 1" >>confdefs.h $as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h + $as_echo "#define BROKEN_TCGETATTR_ICANON 1" >>confdefs.h + TEST_SHELL=$SHELL # let configure find us a capable shell case "$host" in *-*-sysv5SCO_SV*) # SCO OpenServer 6.x @@ -9631,6 +9682,8 @@ if test "$ac_res" != no; then : fi +# "Particular Function Checks" +# see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html for ac_func in strftime do : ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime" @@ -9686,6 +9739,149 @@ fi fi done +for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 +$as_echo_n "checking for GNU libc compatible malloc... " >&6; } +if ${ac_cv_func_malloc_0_nonnull+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_malloc_0_nonnull=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *malloc (); +#endif + +int +main () +{ +return ! malloc (0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_malloc_0_nonnull=yes +else + ac_cv_func_malloc_0_nonnull=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } +if test $ac_cv_func_malloc_0_nonnull = yes; then : + +$as_echo "#define HAVE_MALLOC 1" >>confdefs.h + +else + $as_echo "#define HAVE_MALLOC 0" >>confdefs.h + + case " $LIBOBJS " in + *" malloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS malloc.$ac_objext" + ;; +esac + + +$as_echo "#define malloc rpl_malloc" >>confdefs.h + +fi + + +for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5 +$as_echo_n "checking for GNU libc compatible realloc... " >&6; } +if ${ac_cv_func_realloc_0_nonnull+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_realloc_0_nonnull=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *realloc (); +#endif + +int +main () +{ +return ! realloc (0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_realloc_0_nonnull=yes +else + ac_cv_func_realloc_0_nonnull=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_realloc_0_nonnull" >&6; } +if test $ac_cv_func_realloc_0_nonnull = yes; then : + +$as_echo "#define HAVE_REALLOC 1" >>confdefs.h + +else + $as_echo "#define HAVE_REALLOC 0" >>confdefs.h + + case " $LIBOBJS " in + *" realloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS realloc.$ac_objext" + ;; +esac + + +$as_echo "#define realloc rpl_realloc" >>confdefs.h + +fi + + +# autoconf doesn't have AC_FUNC_CALLOC so fake it if malloc returns NULL; +if test "x$ac_cv_func_malloc_0_nonnull" != "xyes"; then + +$as_echo "#define HAVE_CALLOC 0" >>confdefs.h + + +$as_echo "#define calloc rpl_calloc" >>confdefs.h + +fi # Check for ALTDIRFUNC glob() extension { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLOB_ALTDIRFUNC support" >&5 @@ -10068,6 +10264,7 @@ fi else LIBS="$LIBS `$LDNSCONFIG --libs`" CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`" + ldns=yes fi elif test "x$withval" != "xno" ; then CPPFLAGS="$CPPFLAGS -I${withval}/include" @@ -10647,6 +10844,7 @@ for ac_func in \ fchmod \ fchown \ freeaddrinfo \ + freezero \ fstatfs \ fstatvfs \ futimes \ @@ -10655,6 +10853,7 @@ for ac_func in \ getgrouplist \ getnameinfo \ getopt \ + getpagesize \ getpeereid \ getpeerucred \ getpgid \ @@ -10685,6 +10884,7 @@ for ac_func in \ readpassphrase \ reallocarray \ recvmsg \ + recallocarray \ rresvport_af \ sendmsg \ setdtablesize \ @@ -10718,6 +10918,7 @@ for ac_func in \ strnlen \ strnvis \ strptime \ + strsignal \ strtonum \ strtoll \ strtoul \ @@ -12484,7 +12685,11 @@ if ac_fn_c_try_run "$LINENO"; then : 10000*|0*) as_fn_error $? "OpenSSL >= 1.0.1 required (have \"$ssl_library_ver\")" "$LINENO" 5 ;; - *) ;; + 100*) ;; # 1.0.x + 200*) ;; # LibreSSL + *) + as_fn_error $? "OpenSSL >= 1.1.0 is not yet supported (have \"$ssl_library_ver\")" "$LINENO" 5 + ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssl_library_ver" >&5 $as_echo "$ssl_library_ver" >&6; } @@ -13053,9 +13258,6 @@ $as_echo_n "checking whether OpenSSL has NID_X9_62_prime256v1... " >&6; } #include #include #include - #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ - # error "OpenSSL < 0.9.8g has unreliable ECC code" - #endif int main () @@ -13091,9 +13293,6 @@ $as_echo_n "checking whether OpenSSL has NID_secp384r1... " >&6; } #include #include #include - #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ - # error "OpenSSL < 0.9.8g has unreliable ECC code" - #endif int main () @@ -13129,9 +13328,6 @@ $as_echo_n "checking whether OpenSSL has NID_secp521r1... " >&6; } #include #include #include - #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ - # error "OpenSSL < 0.9.8g has unreliable ECC code" - #endif int main () @@ -13858,6 +14054,7 @@ $as_echo_n "checking if select works with descriptor rlimit... " >&6; } if test "$cross_compiling" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5 $as_echo "$as_me: WARNING: cross compiling: assuming yes" >&2;} + select_works_with_rlimit=yes else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -13918,6 +14115,7 @@ $as_echo_n "checking if setrlimit(RLIMIT_NOFILE,{0,0}) works... " >&6; } if test "$cross_compiling" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5 $as_echo "$as_me: WARNING: cross compiling: assuming yes" >&2;} + rlimit_nofile_zero_works=yes else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -14052,10 +14250,10 @@ $as_echo "#define SANDBOX_SECCOMP_FILTER 1" >>confdefs.h elif test "x$sandbox_arg" = "xcapsicum" || \ ( test -z "$sandbox_arg" && \ - test "x$ac_cv_header_sys_capability_h" = "xyes" && \ + test "x$ac_cv_header_sys_capsicum_h" = "xyes" && \ test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then - test "x$ac_cv_header_sys_capability_h" != "xyes" && \ - as_fn_error $? "capsicum sandbox requires sys/capability.h header" "$LINENO" 5 + test "x$ac_cv_header_sys_capsicum_h" != "xyes" && \ + as_fn_error $? "capsicum sandbox requires sys/capsicum.h header" "$LINENO" 5 test "x$ac_cv_func_cap_rights_limit" != "xyes" && \ as_fn_error $? "capsicum sandbox requires cap_rights_limit function" "$LINENO" 5 SANDBOX_STYLE="capsicum" @@ -16185,6 +16383,26 @@ cat >>confdefs.h <<_ACEOF _ACEOF +fi + +ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim" "ac_cv_member_struct_stat_st_mtim" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_mtim" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_MTIM 1 +_ACEOF + + +fi + +ac_fn_c_check_member "$LINENO" "struct stat" "st_mtime" "ac_cv_member_struct_stat_st_mtime" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_mtime" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_MTIME 1 +_ACEOF + + fi ac_fn_c_check_member "$LINENO" "struct passwd" "pw_gecos" "ac_cv_member_struct_passwd_pw_gecos" " @@ -19055,6 +19273,9 @@ TEST_MALLOC_OPTIONS=$TEST_MALLOC_OPTIONS UNSUPPORTED_ALGORITHMS=$unsupported_algorithms +CFLAGS="${CFLAGS} ${CFLAGS_AFTER}" +LDFLAGS="${LDFLAGS} ${LDFLAGS_AFTER}" + ac_config_files="$ac_config_files Makefile buildpkg.sh opensshd.init openssh.xml openbsd-compat/Makefile openbsd-compat/regress/Makefile survey.sh" diff --git a/configure.ac b/configure.ac index c2878e3d4415..889f506377c0 100644 --- a/configure.ac +++ b/configure.ac @@ -109,13 +109,10 @@ AC_CHECK_DECL([PR_SET_NO_NEW_PRIVS], [have_linux_no_new_privs=1], , [ ]) openssl=yes -ssh1=no -COMMENT_OUT_RSA1="#no ssh1#" AC_ARG_WITH([openssl], [ --without-openssl Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL** ], [ if test "x$withval" = "xno" ; then openssl=no - ssh1=no fi ] ) @@ -127,31 +124,6 @@ else AC_MSG_RESULT([no]) fi -AC_ARG_WITH([ssh1], - [ --with-ssh1 Enable support for SSH protocol 1], - [ - if test "x$withval" = "xyes" ; then - if test "x$openssl" = "xno" ; then - AC_MSG_ERROR([Cannot enable SSH protocol 1 with OpenSSL disabled]) - fi - ssh1=yes - COMMENT_OUT_RSA1="" - elif test "x$withval" = "xno" ; then - ssh1=no - else - AC_MSG_ERROR([unknown --with-ssh1 argument]) - fi - ] -) -AC_MSG_CHECKING([whether SSH protocol 1 support is enabled]) -if test "x$ssh1" = "xyes" ; then - AC_MSG_RESULT([yes]) - AC_DEFINE_UNQUOTED([WITH_SSH1], [1], [include SSH protocol version 1 support]) - AC_SUBST([COMMENT_OUT_RSA1]) -else - AC_MSG_RESULT([no]) -fi - use_stack_protector=1 use_toolchain_hardening=1 AC_ARG_WITH([stackprotect], @@ -179,6 +151,7 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int main(void) { return 0; }]])], CFLAGS="$saved_CFLAGS" if test "$GCC" = "yes" || test "$GCC" = "egcs"; then + OSSH_CHECK_CFLAG_COMPILE([-pipe]) OSSH_CHECK_CFLAG_COMPILE([-Qunused-arguments]) OSSH_CHECK_CFLAG_COMPILE([-Wunknown-warning-option]) OSSH_CHECK_CFLAG_COMPILE([-Wall]) @@ -190,8 +163,8 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then OSSH_CHECK_CFLAG_COMPILE([-Wpointer-sign], [-Wno-pointer-sign]) OSSH_CHECK_CFLAG_COMPILE([-Wunused-result], [-Wno-unused-result]) OSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing]) - OSSH_CHECK_CFLAG_COMPILE([-D_FORTIFY_SOURCE=2]) if test "x$use_toolchain_hardening" = "x1"; then + OSSH_CHECK_CFLAG_COMPILE([-D_FORTIFY_SOURCE=2]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,relro]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,now]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,noexecstack]) @@ -316,6 +289,16 @@ AC_ARG_WITH([cflags], fi ] ) + +AC_ARG_WITH([cflags-after], + [ --with-cflags-after Specify additional flags to pass to compiler after configure], + [ + if test -n "$withval" && test "x$withval" != "xno" && \ + test "x${withval}" != "xyes"; then + CFLAGS_AFTER="$withval" + fi + ] +) AC_ARG_WITH([cppflags], [ --with-cppflags Specify additional flags to pass to preprocessor] , [ @@ -334,6 +317,15 @@ AC_ARG_WITH([ldflags], fi ] ) +AC_ARG_WITH([ldflags-after], + [ --with-ldflags-after Specify additional flags to pass to linker after configure], + [ + if test -n "$withval" && test "x$withval" != "xno" && \ + test "x${withval}" != "xyes"; then + LDFLAGS_AFTER="$withval" + fi + ] +) AC_ARG_WITH([libs], [ --with-libs Specify additional libraries to link with], [ @@ -397,7 +389,6 @@ AC_CHECK_HEADERS([ \ sys/audit.h \ sys/bitypes.h \ sys/bsdtty.h \ - sys/capability.h \ sys/cdefs.h \ sys/dir.h \ sys/mman.h \ @@ -429,6 +420,13 @@ AC_CHECK_HEADERS([ \ wchar.h \ ]) +# sys/capsicum.h requires sys/types.h +AC_CHECK_HEADERS([sys/capsicum.h], [], [], [ +#ifdef HAVE_SYS_TYPES_H +# include +#endif +]) + # lastlog.h requires sys/time.h to be included first on Solaris AC_CHECK_HEADERS([lastlog.h], [], [], [ #ifdef HAVE_SYS_TIME_H @@ -1007,6 +1005,7 @@ mips-sony-bsd|mips-sony-newsos4) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([PASSWD_NEEDS_USERNAME]) + AC_DEFINE([BROKEN_TCGETATTR_ICANON]) TEST_SHELL=$SHELL # let configure find us a capable shell case "$host" in *-*-sysv5SCO_SV*) # SCO OpenServer 6.x @@ -1332,7 +1331,17 @@ AC_CHECK_FUNCS([fmt_scaled scan_scaled login logout openpty updwtmp logwtmp]) AC_SEARCH_LIBS([inet_ntop], [resolv nsl]) AC_SEARCH_LIBS([gethostbyname], [resolv nsl]) +# "Particular Function Checks" +# see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html AC_FUNC_STRFTIME +AC_FUNC_MALLOC +AC_FUNC_REALLOC +# autoconf doesn't have AC_FUNC_CALLOC so fake it if malloc returns NULL; +if test "x$ac_cv_func_malloc_0_nonnull" != "xyes"; then + AC_DEFINE(HAVE_CALLOC, 0, [calloc(x, 0) returns NULL]) + AC_DEFINE(calloc, rpl_calloc, + [Define to rpl_calloc if the replacement function should be used.]) +fi # Check for ALTDIRFUNC glob() extension AC_MSG_CHECKING([for GLOB_ALTDIRFUNC support]) @@ -1486,6 +1495,7 @@ AC_ARG_WITH(ldns, else LIBS="$LIBS `$LDNSCONFIG --libs`" CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`" + ldns=yes fi elif test "x$withval" != "xno" ; then CPPFLAGS="$CPPFLAGS -I${withval}/include" @@ -1696,6 +1706,7 @@ AC_CHECK_FUNCS([ \ fchmod \ fchown \ freeaddrinfo \ + freezero \ fstatfs \ fstatvfs \ futimes \ @@ -1704,6 +1715,7 @@ AC_CHECK_FUNCS([ \ getgrouplist \ getnameinfo \ getopt \ + getpagesize \ getpeereid \ getpeerucred \ getpgid \ @@ -1734,6 +1746,7 @@ AC_CHECK_FUNCS([ \ readpassphrase \ reallocarray \ recvmsg \ + recallocarray \ rresvport_af \ sendmsg \ setdtablesize \ @@ -1767,6 +1780,7 @@ AC_CHECK_FUNCS([ \ strnlen \ strnvis \ strptime \ + strsignal \ strtonum \ strtoll \ strtoul \ @@ -2535,7 +2549,11 @@ if test "x$openssl" = "xyes" ; then 10000*|0*) AC_MSG_ERROR([OpenSSL >= 1.0.1 required (have "$ssl_library_ver")]) ;; - *) ;; + 100*) ;; # 1.0.x + 200*) ;; # LibreSSL + *) + AC_MSG_ERROR([OpenSSL >= 1.1.0 is not yet supported (have "$ssl_library_ver")]) + ;; esac AC_MSG_RESULT([$ssl_library_ver]) ], @@ -2768,9 +2786,6 @@ if test "x$openssl" = "xyes" ; then #include #include #include - #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ - # error "OpenSSL < 0.9.8g has unreliable ECC code" - #endif ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); const EVP_MD *m = EVP_sha256(); /* We need this too */ @@ -2789,9 +2804,6 @@ if test "x$openssl" = "xyes" ; then #include #include #include - #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ - # error "OpenSSL < 0.9.8g has unreliable ECC code" - #endif ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1); const EVP_MD *m = EVP_sha384(); /* We need this too */ @@ -2810,9 +2822,6 @@ if test "x$openssl" = "xyes" ; then #include #include #include - #if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */ - # error "OpenSSL < 0.9.8g has unreliable ECC code" - #endif ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); const EVP_MD *m = EVP_sha512(); /* We need this too */ @@ -3197,7 +3206,8 @@ AC_RUN_IFELSE( select_works_with_rlimit=yes], [AC_MSG_RESULT([no]) select_works_with_rlimit=no], - [AC_MSG_WARN([cross compiling: assuming yes])] + [AC_MSG_WARN([cross compiling: assuming yes]) + select_works_with_rlimit=yes] ) AC_MSG_CHECKING([if setrlimit(RLIMIT_NOFILE,{0,0}) works]) @@ -3223,7 +3233,8 @@ AC_RUN_IFELSE( rlimit_nofile_zero_works=yes], [AC_MSG_RESULT([no]) rlimit_nofile_zero_works=no], - [AC_MSG_WARN([cross compiling: assuming yes])] + [AC_MSG_WARN([cross compiling: assuming yes]) + rlimit_nofile_zero_works=yes] ) AC_MSG_CHECKING([if setrlimit RLIMIT_FSIZE works]) @@ -3286,10 +3297,10 @@ elif test "x$sandbox_arg" = "xseccomp_filter" || \ AC_DEFINE([SANDBOX_SECCOMP_FILTER], [1], [Sandbox using seccomp filter]) elif test "x$sandbox_arg" = "xcapsicum" || \ ( test -z "$sandbox_arg" && \ - test "x$ac_cv_header_sys_capability_h" = "xyes" && \ + test "x$ac_cv_header_sys_capsicum_h" = "xyes" && \ test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then - test "x$ac_cv_header_sys_capability_h" != "xyes" && \ - AC_MSG_ERROR([capsicum sandbox requires sys/capability.h header]) + test "x$ac_cv_header_sys_capsicum_h" != "xyes" && \ + AC_MSG_ERROR([capsicum sandbox requires sys/capsicum.h header]) test "x$ac_cv_func_cap_rights_limit" != "xyes" && \ AC_MSG_ERROR([capsicum sandbox requires cap_rights_limit function]) SANDBOX_STYLE="capsicum" @@ -3845,6 +3856,8 @@ OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmpx.h], [HAVE_TIME_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_tv], [utmpx.h], [HAVE_TV_IN_UTMPX]) AC_CHECK_MEMBERS([struct stat.st_blksize]) +AC_CHECK_MEMBERS([struct stat.st_mtim]) +AC_CHECK_MEMBERS([struct stat.st_mtime]) AC_CHECK_MEMBERS([struct passwd.pw_gecos, struct passwd.pw_class, struct passwd.pw_change, struct passwd.pw_expire], [], [], [[ @@ -5044,6 +5057,9 @@ AC_SUBST([TEST_SSH_UTF8], [$TEST_SSH_UTF8]) AC_SUBST([TEST_MALLOC_OPTIONS], [$TEST_MALLOC_OPTIONS]) AC_SUBST([UNSUPPORTED_ALGORITHMS], [$unsupported_algorithms]) +CFLAGS="${CFLAGS} ${CFLAGS_AFTER}" +LDFLAGS="${LDFLAGS} ${LDFLAGS_AFTER}" + AC_EXEEXT AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \ openbsd-compat/Makefile openbsd-compat/regress/Makefile \ diff --git a/contrib/aix/README b/contrib/aix/README index 2a299350abb0..4a11ae7038f9 100644 --- a/contrib/aix/README +++ b/contrib/aix/README @@ -35,7 +35,7 @@ The script treats all packages as USR packages (not ROOT+USR when appropriate). It seems to work, though...... If there are any patches to this that have not yet been integrated they -may be found at http://www.zip.com.au/~dtucker/openssh/. +may be found at http://www.dtucker.net/openssh/. Disclaimer: diff --git a/contrib/redhat/openssh.spec b/contrib/redhat/openssh.spec index 7de45457a742..a96a36e492d6 100644 --- a/contrib/redhat/openssh.spec +++ b/contrib/redhat/openssh.spec @@ -1,4 +1,4 @@ -%define ver 7.5p1 +%define ver 7.6p1 %define rel 1 # OpenSSH privilege separation requires a user & group ID diff --git a/contrib/ssh-copy-id b/contrib/ssh-copy-id index bef5c95d9061..b83b83619896 100644 --- a/contrib/ssh-copy-id +++ b/contrib/ssh-copy-id @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (c) 1999-2013 Philip Hands +# Copyright (c) 1999-2016 Philip Hands # 2013 Martin Kletzander # 2010 Adeodato =?iso-8859-1?Q?Sim=F3?= # 2010 Eric Moret @@ -56,7 +56,8 @@ then fi fi -DEFAULT_PUB_ID_FILE="$HOME/$(cd "$HOME" ; ls -t .ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1)" +most_recent_id="$(cd "$HOME" ; ls -t .ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1)" +DEFAULT_PUB_ID_FILE="${most_recent_id:+$HOME/}$most_recent_id" usage () { printf 'Usage: %s [-h|-?|-f|-n] [-i [identity_file]] [-p port] [[-o ] ...] [user@]hostname\n' "$0" >&2 @@ -74,6 +75,11 @@ quote() { use_id_file() { local L_ID_FILE="$1" + if [ -z "$L_ID_FILE" ] ; then + printf "%s: ERROR: no ID file found\n" "$0" + exit 1 + fi + if expr "$L_ID_FILE" : ".*\.pub$" >/dev/null ; then PUB_ID_FILE="$L_ID_FILE" else @@ -287,9 +293,10 @@ case "$REMOTE_VERSION" in *) # Assuming that the remote host treats ~/.ssh/authorized_keys as one might expect populate_new_ids 0 - # in ssh below - to defend against quirky remote shells: use 'exec sh -c' to get POSIX; 'cd' to be at $HOME; and all on one line, because tcsh. + # in ssh below - to defend against quirky remote shells: use 'exec sh -c' to get POSIX; + # 'cd' to be at $HOME; add a newline if it's missing; and all on one line, because tcsh. [ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | \ - ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \ + ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && { [ -z "'`tail -1c .ssh/authorized_keys 2>/dev/null`'" ] || echo >> .ssh/authorized_keys ; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \ || exit 1 ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l) ;; diff --git a/contrib/suse/openssh.spec b/contrib/suse/openssh.spec index e62be39d0aac..fdb3578cbd4e 100644 --- a/contrib/suse/openssh.spec +++ b/contrib/suse/openssh.spec @@ -13,7 +13,7 @@ Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation Name: openssh -Version: 7.5p1 +Version: 7.6p1 URL: https://www.openssh.com/ Release: 1 Source0: openssh-%{version}.tar.gz diff --git a/deattack.c b/deattack.c deleted file mode 100644 index e76481a6d08e..000000000000 --- a/deattack.c +++ /dev/null @@ -1,165 +0,0 @@ -/* $OpenBSD: deattack.c,v 1.32 2015/01/20 23:14:00 deraadt Exp $ */ -/* - * Cryptographic attack detector for ssh - source code - * - * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina. - * - * All rights reserved. Redistribution and use in source and binary - * forms, with or without modification, are permitted provided that - * this copyright notice is retained. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR - * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS - * SOFTWARE. - * - * Ariel Futoransky - * - */ - -#include "includes.h" - -#include -#include -#include - -#include "deattack.h" -#include "crc32.h" -#include "sshbuf.h" -#include "misc.h" - -/* - * CRC attack detection has a worst-case behaviour that is O(N^3) over - * the number of identical blocks in a packet. This behaviour can be - * exploited to create a limited denial of service attack. - * - * However, because we are dealing with encrypted data, identical - * blocks should only occur every 2^35 maximally-sized packets or so. - * Consequently, we can detect this DoS by looking for identical blocks - * in a packet. - * - * The parameter below determines how many identical blocks we will - * accept in a single packet, trading off between attack detection and - * likelihood of terminating a legitimate connection. A value of 32 - * corresponds to an average of 2^40 messages before an attack is - * misdetected - */ -#define MAX_IDENTICAL 32 - -/* SSH Constants */ -#define SSH_MAXBLOCKS (32 * 1024) -#define SSH_BLOCKSIZE (8) - -/* Hashing constants */ -#define HASH_MINSIZE (8 * 1024) -#define HASH_ENTRYSIZE (2) -#define HASH_FACTOR(x) ((x)*3/2) -#define HASH_UNUSEDCHAR (0xff) -#define HASH_UNUSED (0xffff) -#define HASH_IV (0xfffe) - -#define HASH_MINBLOCKS (7*SSH_BLOCKSIZE) - - -/* Hash function (Input keys are cipher results) */ -#define HASH(x) PEEK_U32(x) - -#define CMP(a, b) (memcmp(a, b, SSH_BLOCKSIZE)) - -static void -crc_update(u_int32_t *a, u_int32_t b) -{ - b ^= *a; - *a = ssh_crc32((u_char *)&b, sizeof(b)); -} - -/* detect if a block is used in a particular pattern */ -static int -check_crc(const u_char *S, const u_char *buf, u_int32_t len) -{ - u_int32_t crc; - const u_char *c; - - crc = 0; - for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) { - if (!CMP(S, c)) { - crc_update(&crc, 1); - crc_update(&crc, 0); - } else { - crc_update(&crc, 0); - crc_update(&crc, 0); - } - } - return crc == 0; -} - -void -deattack_init(struct deattack_ctx *dctx) -{ - bzero(dctx, sizeof(*dctx)); - dctx->n = HASH_MINSIZE / HASH_ENTRYSIZE; -} - -/* Detect a crc32 compensation attack on a packet */ -int -detect_attack(struct deattack_ctx *dctx, const u_char *buf, u_int32_t len) -{ - u_int32_t i, j, l, same; - u_int16_t *tmp; - const u_char *c, *d; - - if (len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) || - len % SSH_BLOCKSIZE != 0) - return DEATTACK_ERROR; - for (l = dctx->n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2) - ; - - if (dctx->h == NULL) { - if ((dctx->h = calloc(l, HASH_ENTRYSIZE)) == NULL) - return DEATTACK_ERROR; - dctx->n = l; - } else { - if (l > dctx->n) { - if ((tmp = reallocarray(dctx->h, l, HASH_ENTRYSIZE)) - == NULL) { - free(dctx->h); - dctx->h = NULL; - return DEATTACK_ERROR; - } - dctx->h = tmp; - dctx->n = l; - } - } - - if (len <= HASH_MINBLOCKS) { - for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) { - for (d = buf; d < c; d += SSH_BLOCKSIZE) { - if (!CMP(c, d)) { - if ((check_crc(c, buf, len))) - return DEATTACK_DETECTED; - else - break; - } - } - } - return DEATTACK_OK; - } - memset(dctx->h, HASH_UNUSEDCHAR, dctx->n * HASH_ENTRYSIZE); - - for (c = buf, same = j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) { - for (i = HASH(c) & (dctx->n - 1); dctx->h[i] != HASH_UNUSED; - i = (i + 1) & (dctx->n - 1)) { - if (!CMP(c, buf + dctx->h[i] * SSH_BLOCKSIZE)) { - if (++same > MAX_IDENTICAL) - return DEATTACK_DOS_DETECTED; - if (check_crc(c, buf, len)) - return DEATTACK_DETECTED; - else - break; - } - } - dctx->h[i] = j; - } - return DEATTACK_OK; -} diff --git a/deattack.h b/deattack.h deleted file mode 100644 index ce67a30ffdd3..000000000000 --- a/deattack.h +++ /dev/null @@ -1,38 +0,0 @@ -/* $OpenBSD: deattack.h,v 1.11 2015/01/19 19:52:16 markus Exp $ */ - -/* - * Cryptographic attack detector for ssh - Header file - * - * Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina. - * - * All rights reserved. Redistribution and use in source and binary - * forms, with or without modification, are permitted provided that - * this copyright notice is retained. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR - * CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS - * SOFTWARE. - * - * Ariel Futoransky - * - */ - -#ifndef _DEATTACK_H -#define _DEATTACK_H - -/* Return codes */ -#define DEATTACK_OK 0 -#define DEATTACK_DETECTED 1 -#define DEATTACK_DOS_DETECTED 2 -#define DEATTACK_ERROR 3 - -struct deattack_ctx { - u_int16_t *h; - u_int32_t n; -}; - -void deattack_init(struct deattack_ctx *); -int detect_attack(struct deattack_ctx *, const u_char *, u_int32_t); -#endif diff --git a/defines.h b/defines.h index c89f85a8d9c0..f1662edcfea0 100644 --- a/defines.h +++ b/defines.h @@ -328,6 +328,28 @@ typedef unsigned int size_t; #define SIZE_MAX SIZE_T_MAX #endif +#ifndef INT32_MAX +# if (SIZEOF_INT == 4) +# define INT32_MAX INT_MAX +# elif (SIZEOF_LONG == 4) +# define INT32_MAX LONG_MAX +# else +# error "need INT32_MAX" +# endif +#endif + +#ifndef INT64_MAX +# if (SIZEOF_INT == 8) +# define INT64_MAX INT_MAX +# elif (SIZEOF_LONG == 8) +# define INT64_MAX LONG_MAX +# elif (SIZEOF_LONG_LONG_INT == 8) +# define INT64_MAX LLONG_MAX +# else +# error "need INT64_MAX" +# endif +#endif + #ifndef HAVE_SSIZE_T typedef int ssize_t; # define HAVE_SSIZE_T @@ -497,6 +519,13 @@ struct winsize { } #endif +#ifndef timespeccmp +#define timespeccmp(tsp, usp, cmp) \ + (((tsp)->tv_sec == (usp)->tv_sec) ? \ + ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ + ((tsp)->tv_sec cmp (usp)->tv_sec)) +#endif + #ifndef __P # define __P(x) x #endif diff --git a/digest-libc.c b/digest-libc.c index 40db00274d74..c2b0b2403d11 100644 --- a/digest-libc.c +++ b/digest-libc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: digest-libc.c,v 1.5 2015/05/05 02:48:17 jsg Exp $ */ +/* $OpenBSD: digest-libc.c,v 1.6 2017/05/08 22:57:38 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * Copyright (c) 2014 Markus Friedl. All rights reserved. @@ -68,16 +68,6 @@ const struct ssh_digest digests[SSH_DIGEST_MAX] = { (md_update_fn *) MD5Update, (md_final_fn *) MD5Final }, - { - SSH_DIGEST_RIPEMD160, - "RIPEMD160", - RMD160_BLOCK_LENGTH, - RMD160_DIGEST_LENGTH, - sizeof(RMD160_CTX), - (md_init_fn *) RMD160Init, - (md_update_fn *) RMD160Update, - (md_final_fn *) RMD160Final - }, { SSH_DIGEST_SHA1, "SHA1", diff --git a/digest-openssl.c b/digest-openssl.c index c55ceb93f9d4..2770999295ea 100644 --- a/digest-openssl.c +++ b/digest-openssl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: digest-openssl.c,v 1.6 2017/03/10 02:59:51 dtucker Exp $ */ +/* $OpenBSD: digest-openssl.c,v 1.7 2017/05/08 22:57:38 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * @@ -56,7 +56,6 @@ struct ssh_digest { /* NB. Indexed directly by algorithm number */ const struct ssh_digest digests[] = { { SSH_DIGEST_MD5, "MD5", 16, EVP_md5 }, - { SSH_DIGEST_RIPEMD160, "RIPEMD160", 20, EVP_ripemd160 }, { SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 }, { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 }, { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 }, diff --git a/digest.h b/digest.h index 3fe07346852b..274574d0e544 100644 --- a/digest.h +++ b/digest.h @@ -1,4 +1,4 @@ -/* $OpenBSD: digest.h,v 1.7 2014/12/21 22:27:56 djm Exp $ */ +/* $OpenBSD: digest.h,v 1.8 2017/05/08 22:57:38 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * @@ -23,12 +23,11 @@ /* Digest algorithms */ #define SSH_DIGEST_MD5 0 -#define SSH_DIGEST_RIPEMD160 1 -#define SSH_DIGEST_SHA1 2 -#define SSH_DIGEST_SHA256 3 -#define SSH_DIGEST_SHA384 4 -#define SSH_DIGEST_SHA512 5 -#define SSH_DIGEST_MAX 6 +#define SSH_DIGEST_SHA1 1 +#define SSH_DIGEST_SHA256 2 +#define SSH_DIGEST_SHA384 3 +#define SSH_DIGEST_SHA512 4 +#define SSH_DIGEST_MAX 5 struct sshbuf; struct ssh_digest_ctx; diff --git a/dispatch.c b/dispatch.c index aac933e0a501..0b3ea614e150 100644 --- a/dispatch.c +++ b/dispatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.c,v 1.27 2015/05/01 07:10:01 djm Exp $ */ +/* $OpenBSD: dispatch.c,v 1.31 2017/05/31 07:00:13 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -30,7 +30,6 @@ #include #include -#include "ssh1.h" #include "ssh2.h" #include "log.h" #include "dispatch.h" @@ -39,14 +38,11 @@ #include "ssherr.h" int -dispatch_protocol_error(int type, u_int32_t seq, void *ctx) +dispatch_protocol_error(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = active_state; /* XXX */ int r; logit("dispatch_protocol_error: type %d seq %u", type, seq); - if (!compat20) - fatal("protocol error"); if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || (r = sshpkt_put_u32(ssh, seq)) != 0 || (r = sshpkt_send(ssh)) != 0 || @@ -56,7 +52,7 @@ dispatch_protocol_error(int type, u_int32_t seq, void *ctx) } int -dispatch_protocol_ignore(int type, u_int32_t seq, void *ssh) +dispatch_protocol_ignore(int type, u_int32_t seq, struct ssh *ssh) { logit("dispatch_protocol_ignore: type %d seq %u", type, seq); return 0; @@ -89,8 +85,7 @@ ssh_dispatch_set(struct ssh *ssh, int type, dispatch_fn *fn) } int -ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done, - void *ctxt) +ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done) { int r; u_char type; @@ -115,8 +110,7 @@ ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done, ssh->dispatch_skip_packets--; continue; } - /* XXX 'ssh' will replace 'ctxt' later */ - r = (*ssh->dispatch[type])(type, seqnr, ctxt); + r = (*ssh->dispatch[type])(type, seqnr, ssh); if (r != 0) return r; } else { @@ -132,11 +126,10 @@ ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done, } void -ssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done, - void *ctxt) +ssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done) { int r; - if ((r = ssh_dispatch_run(ssh, mode, done, ctxt)) != 0) + if ((r = ssh_dispatch_run(ssh, mode, done)) != 0) sshpkt_fatal(ssh, __func__, r); } diff --git a/dispatch.h b/dispatch.h index cd51dbc0b666..17a6f3db6338 100644 --- a/dispatch.h +++ b/dispatch.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.h,v 1.12 2015/01/19 20:07:45 markus Exp $ */ +/* $OpenBSD: dispatch.h,v 1.14 2017/05/31 07:00:13 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -36,15 +36,15 @@ enum { struct ssh; -typedef int dispatch_fn(int, u_int32_t, void *); +typedef int dispatch_fn(int, u_int32_t, struct ssh *); -int dispatch_protocol_error(int, u_int32_t, void *); -int dispatch_protocol_ignore(int, u_int32_t, void *); +int dispatch_protocol_error(int, u_int32_t, struct ssh *); +int dispatch_protocol_ignore(int, u_int32_t, struct ssh *); void ssh_dispatch_init(struct ssh *, dispatch_fn *); void ssh_dispatch_set(struct ssh *, int, dispatch_fn *); void ssh_dispatch_range(struct ssh *, u_int, u_int, dispatch_fn *); -int ssh_dispatch_run(struct ssh *, int, volatile sig_atomic_t *, void *); -void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *, void *); +int ssh_dispatch_run(struct ssh *, int, volatile sig_atomic_t *); +void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *); #define dispatch_init(dflt) \ ssh_dispatch_init(active_state, (dflt)) @@ -52,7 +52,5 @@ void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *, void *); ssh_dispatch_range(active_state, (from), (to), (fn)) #define dispatch_set(type, fn) \ ssh_dispatch_set(active_state, (type), (fn)) -#define dispatch_run(mode, done, ctxt) \ - ssh_dispatch_run_fatal(active_state, (mode), (done), (ctxt)) #endif diff --git a/dns.c b/dns.c index e813afeae690..6e1abb5300cd 100644 --- a/dns.c +++ b/dns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dns.c,v 1.35 2015/08/20 22:32:42 deraadt Exp $ */ +/* $OpenBSD: dns.c,v 1.37 2017/09/14 04:32:21 djm Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. diff --git a/dns.h b/dns.h index 30e2b19b3d94..68443f7cbbb8 100644 --- a/dns.h +++ b/dns.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dns.h,v 1.15 2015/05/08 06:45:13 djm Exp $ */ +/* $OpenBSD: dns.h,v 1.17 2017/09/14 04:32:21 djm Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. diff --git a/gss-serv.c b/gss-serv.c index 53993d674cfb..6cae720e5d9b 100644 --- a/gss-serv.c +++ b/gss-serv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gss-serv.c,v 1.29 2015/05/22 03:50:02 djm Exp $ */ +/* $OpenBSD: gss-serv.c,v 1.30 2017/06/24 06:34:38 djm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -393,4 +393,13 @@ ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) return (ctx->major); } +/* Privileged */ +const char *ssh_gssapi_displayname(void) +{ + if (gssapi_client.displayname.length == 0 || + gssapi_client.displayname.value == NULL) + return NULL; + return (char *)gssapi_client.displayname.value; +} + #endif diff --git a/hostfile.c b/hostfile.c index e23faa9696af..12f174ff97b1 100644 --- a/hostfile.c +++ b/hostfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hostfile.c,v 1.68 2017/03/10 04:26:06 djm Exp $ */ +/* $OpenBSD: hostfile.c,v 1.71 2017/05/31 09:15:42 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -251,7 +251,7 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx) l->marker == MRK_NONE ? "" : (l->marker == MRK_CA ? "ca " : "revoked "), sshkey_type(l->key), l->path, l->linenum); - if ((tmp = reallocarray(hostkeys->entries, + if ((tmp = recallocarray(hostkeys->entries, hostkeys->num_entries, hostkeys->num_entries + 1, sizeof(*hostkeys->entries))) == NULL) return SSH_ERR_ALLOC_FAIL; hostkeys->entries = tmp; @@ -346,16 +346,11 @@ check_hostkeys_by_key_or_type(struct hostkeys *hostkeys, HostStatus end_return = HOST_NEW; int want_cert = sshkey_is_cert(k); HostkeyMarker want_marker = want_cert ? MRK_CA : MRK_NONE; - int proto = (k ? k->type : keytype) == KEY_RSA1 ? 1 : 2; if (found != NULL) *found = NULL; for (i = 0; i < hostkeys->num_entries; i++) { - if (proto == 1 && hostkeys->entries[i].key->type != KEY_RSA1) - continue; - if (proto == 2 && hostkeys->entries[i].key->type == KEY_RSA1) - continue; if (hostkeys->entries[i].marker != want_marker) continue; if (k == NULL) { @@ -490,13 +485,6 @@ host_delete(struct hostkey_foreach_line *l, void *_ctx) return 0; } - /* XXX might need a knob for this later */ - /* Don't remove RSA1 keys */ - if (l->key->type == KEY_RSA1) { - fprintf(ctx->out, "%s\n", l->line); - return 0; - } - /* * If this line contains one of the keys that we will be * adding later, then don't change it and mark the key for @@ -789,20 +777,7 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, break; } if (!hostfile_read_key(&cp, &kbits, lineinfo.key)) { -#ifdef WITH_SSH1 - sshkey_free(lineinfo.key); - lineinfo.key = sshkey_new(KEY_RSA1); - if (lineinfo.key == NULL) { - error("%s: sshkey_new fail", __func__); - r = SSH_ERR_ALLOC_FAIL; - break; - } - if (!hostfile_read_key(&cp, &kbits, - lineinfo.key)) - goto bad; -#else goto bad; -#endif } lineinfo.keytype = lineinfo.key->type; lineinfo.comment = cp; @@ -817,12 +792,12 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, lineinfo.keytype = sshkey_type_from_name(ktype); /* - * Assume RSA1 if the first component is a short + * Assume legacy RSA1 if the first component is a short * decimal number. */ if (lineinfo.keytype == KEY_UNSPEC && l < 8 && strspn(ktype, "0123456789") == l) - lineinfo.keytype = KEY_RSA1; + goto bad; /* * Check that something other than whitespace follows diff --git a/includes.h b/includes.h index 497a038b2373..0fd71792e1ac 100644 --- a/includes.h +++ b/includes.h @@ -93,6 +93,9 @@ #ifdef HAVE_SYS_SYSMACROS_H # include /* For MIN, MAX, etc */ #endif +#ifdef HAVE_SYS_TIME_H +# include /* for timespeccmp if present */ +#endif #ifdef HAVE_SYS_MMAN_H #include /* for MAP_ANONYMOUS */ #endif diff --git a/kex.c b/kex.c index cf4ac0dc574d..d5d5a9dae996 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.131 2017/03/15 07:07:39 markus Exp $ */ +/* $OpenBSD: kex.c,v 1.134 2017/06/13 12:13:59 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -54,17 +54,9 @@ #include "sshbuf.h" #include "digest.h" -#if OPENSSL_VERSION_NUMBER >= 0x00907000L -# if defined(HAVE_EVP_SHA256) -# define evp_ssh_sha256 EVP_sha256 -# else -extern const EVP_MD *evp_ssh_sha256(void); -# endif -#endif - /* prototype */ static int kex_choose_conf(struct ssh *); -static int kex_input_newkeys(int, u_int32_t, void *); +static int kex_input_newkeys(int, u_int32_t, struct ssh *); static const char *proposal_names[PROPOSAL_MAX] = { "KEX algorithms", @@ -323,9 +315,8 @@ kex_prop_free(char **proposal) /* ARGSUSED */ static int -kex_protocol_error(int type, u_int32_t seq, void *ctxt) +kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = active_state; /* XXX */ int r; error("kex protocol error: type %d seq %u", type, seq); @@ -383,12 +374,13 @@ kex_send_newkeys(struct ssh *ssh) } int -kex_input_ext_info(int type, u_int32_t seq, void *ctxt) +kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; u_int32_t i, ninfo; - char *name, *val, *found; + char *name, *found; + u_char *val; + size_t vlen; int r; debug("SSH2_MSG_EXT_INFO received"); @@ -398,12 +390,17 @@ kex_input_ext_info(int type, u_int32_t seq, void *ctxt) for (i = 0; i < ninfo; i++) { if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0) return r; - if ((r = sshpkt_get_cstring(ssh, &val, NULL)) != 0) { + if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) { free(name); return r; } - debug("%s: %s=<%s>", __func__, name, val); if (strcmp(name, "server-sig-algs") == 0) { + /* Ensure no \0 lurking in value */ + if (memchr(val, '\0', vlen) != NULL) { + error("%s: nul byte in %s", __func__, name); + return SSH_ERR_INVALID_FORMAT; + } + debug("%s: %s=<%s>", __func__, name, val); found = match_list("rsa-sha2-256", val, NULL); if (found) { kex->rsa_sha2 = 256; @@ -414,7 +411,8 @@ kex_input_ext_info(int type, u_int32_t seq, void *ctxt) kex->rsa_sha2 = 512; free(found); } - } + } else + debug("%s: %s (unrecognised)", __func__, name); free(name); free(val); } @@ -422,9 +420,8 @@ kex_input_ext_info(int type, u_int32_t seq, void *ctxt) } static int -kex_input_newkeys(int type, u_int32_t seq, void *ctxt) +kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; int r; @@ -475,9 +472,8 @@ kex_send_kexinit(struct ssh *ssh) /* ARGSUSED */ int -kex_input_kexinit(int type, u_int32_t seq, void *ctxt) +kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; const u_char *ptr; u_int i; @@ -988,47 +984,6 @@ kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen, } #endif -#ifdef WITH_SSH1 -int -derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, - u_int8_t cookie[8], u_int8_t id[16]) -{ - u_int8_t hbuf[2048], sbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH]; - struct ssh_digest_ctx *hashctx = NULL; - size_t hlen, slen; - int r; - - hlen = BN_num_bytes(host_modulus); - slen = BN_num_bytes(server_modulus); - if (hlen < (512 / 8) || (u_int)hlen > sizeof(hbuf) || - slen < (512 / 8) || (u_int)slen > sizeof(sbuf)) - return SSH_ERR_KEY_BITS_MISMATCH; - if (BN_bn2bin(host_modulus, hbuf) <= 0 || - BN_bn2bin(server_modulus, sbuf) <= 0) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (ssh_digest_update(hashctx, hbuf, hlen) != 0 || - ssh_digest_update(hashctx, sbuf, slen) != 0 || - ssh_digest_update(hashctx, cookie, 8) != 0 || - ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5)); - r = 0; - out: - ssh_digest_free(hashctx); - explicit_bzero(hbuf, sizeof(hbuf)); - explicit_bzero(sbuf, sizeof(sbuf)); - explicit_bzero(obuf, sizeof(obuf)); - return r; -} -#endif #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void diff --git a/kex.h b/kex.h index 3794f21278c6..01bb3986abfa 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.81 2016/09/28 21:44:52 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.83 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -181,8 +181,8 @@ int kex_prop2buf(struct sshbuf *, char *proposal[PROPOSAL_MAX]); void kex_prop_free(char **); int kex_send_kexinit(struct ssh *); -int kex_input_kexinit(int, u_int32_t, void *); -int kex_input_ext_info(int, u_int32_t, void *); +int kex_input_kexinit(int, u_int32_t, struct ssh *); +int kex_input_ext_info(int, u_int32_t, struct ssh *); int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *); int kex_derive_keys_bn(struct ssh *, u_char *, u_int, const BIGNUM *); int kex_send_newkeys(struct ssh *); @@ -225,9 +225,6 @@ int kexc25519_shared_key(const u_char key[CURVE25519_SIZE], __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); -int -derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]); - #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void dump_digest(char *, u_char *, int); #endif diff --git a/kexc25519c.c b/kexc25519c.c index b7ef65dc31ae..e488013e93cd 100644 --- a/kexc25519c.c +++ b/kexc25519c.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexc25519c.c,v 1.7 2015/01/26 06:10:03 djm Exp $ */ +/* $OpenBSD: kexc25519c.c,v 1.8 2017/05/31 04:17:12 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -44,7 +44,7 @@ #include "ssherr.h" static int -input_kex_c25519_reply(int type, u_int32_t seq, void *ctxt); +input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh); int kexc25519_client(struct ssh *ssh) @@ -69,9 +69,8 @@ kexc25519_client(struct ssh *ssh) } static int -input_kex_c25519_reply(int type, u_int32_t seq, void *ctxt) +input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; struct sshkey *server_host_key = NULL; struct sshbuf *shared_secret = NULL; diff --git a/kexc25519s.c b/kexc25519s.c index 4e77622b0b2f..0a008d44746f 100644 --- a/kexc25519s.c +++ b/kexc25519s.c @@ -41,7 +41,7 @@ #include "sshbuf.h" #include "ssherr.h" -static int input_kex_c25519_init(int, u_int32_t, void *); +static int input_kex_c25519_init(int, u_int32_t, struct ssh *); int kexc25519_server(struct ssh *ssh) @@ -52,9 +52,8 @@ kexc25519_server(struct ssh *ssh) } static int -input_kex_c25519_init(int type, u_int32_t seq, void *ctxt) +input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; struct sshkey *server_host_private, *server_host_public; struct sshbuf *shared_secret = NULL; diff --git a/kexdhc.c b/kexdhc.c index ad3975f09ee7..9864ee2ec92e 100644 --- a/kexdhc.c +++ b/kexdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhc.c,v 1.19 2016/05/02 10:26:04 djm Exp $ */ +/* $OpenBSD: kexdhc.c,v 1.20 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -49,7 +49,7 @@ #include "ssherr.h" #include "sshbuf.h" -static int input_kex_dh(int, u_int32_t, void *); +static int input_kex_dh(int, u_int32_t, struct ssh *); int kexdh_client(struct ssh *ssh) @@ -100,9 +100,8 @@ kexdh_client(struct ssh *ssh) } static int -input_kex_dh(int type, u_int32_t seq, void *ctxt) +input_kex_dh(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; struct sshkey *server_host_key = NULL; diff --git a/kexdhs.c b/kexdhs.c index 108f664278b0..81ce56d7a5ad 100644 --- a/kexdhs.c +++ b/kexdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhs.c,v 1.24 2016/05/02 10:26:04 djm Exp $ */ +/* $OpenBSD: kexdhs.c,v 1.25 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -49,7 +49,7 @@ #include "ssherr.h" #include "sshbuf.h" -static int input_kex_dh_init(int, u_int32_t, void *); +static int input_kex_dh_init(int, u_int32_t, struct ssh *); int kexdh_server(struct ssh *ssh) @@ -91,9 +91,8 @@ kexdh_server(struct ssh *ssh) } int -input_kex_dh_init(int type, u_int32_t seq, void *ctxt) +input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; struct sshkey *server_host_public, *server_host_private; diff --git a/kexecdhc.c b/kexecdhc.c index 90220ce8205d..d8a8b660fd56 100644 --- a/kexecdhc.c +++ b/kexecdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhc.c,v 1.10 2015/01/26 06:10:03 djm Exp $ */ +/* $OpenBSD: kexecdhc.c,v 1.11 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -49,7 +49,7 @@ #include "ssherr.h" #include "sshbuf.h" -static int input_kex_ecdh_reply(int, u_int32_t, void *); +static int input_kex_ecdh_reply(int, u_int32_t, struct ssh *); int kexecdh_client(struct ssh *ssh) @@ -95,9 +95,8 @@ kexecdh_client(struct ssh *ssh) } static int -input_kex_ecdh_reply(int type, u_int32_t seq, void *ctxt) +input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; const EC_GROUP *group; EC_POINT *server_public = NULL; diff --git a/kexecdhs.c b/kexecdhs.c index ccdbf70b1cf6..dc24a3af609b 100644 --- a/kexecdhs.c +++ b/kexecdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhs.c,v 1.15 2015/12/04 16:41:28 markus Exp $ */ +/* $OpenBSD: kexecdhs.c,v 1.16 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -47,7 +47,7 @@ #include "ssherr.h" #include "sshbuf.h" -static int input_kex_ecdh_init(int, u_int32_t, void *); +static int input_kex_ecdh_init(int, u_int32_t, struct ssh *); int kexecdh_server(struct ssh *ssh) @@ -58,9 +58,8 @@ kexecdh_server(struct ssh *ssh) } static int -input_kex_ecdh_init(int type, u_int32_t seq, void *ctxt) +input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; EC_POINT *client_public; EC_KEY *server_key = NULL; diff --git a/kexgexc.c b/kexgexc.c index ad0d1c8c0ae1..cd11287525b6 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.23 2016/09/12 01:22:38 deraadt Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.25 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -51,8 +51,8 @@ #include "sshbuf.h" #include "misc.h" -static int input_kex_dh_gex_group(int, u_int32_t, void *); -static int input_kex_dh_gex_reply(int, u_int32_t, void *); +static int input_kex_dh_gex_group(int, u_int32_t, struct ssh *); +static int input_kex_dh_gex_reply(int, u_int32_t, struct ssh *); int kexgex_client(struct ssh *ssh) @@ -89,9 +89,8 @@ kexgex_client(struct ssh *ssh) } static int -input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt) +input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; BIGNUM *p = NULL, *g = NULL; int r, bits; @@ -143,9 +142,8 @@ input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt) } static int -input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt) +input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; struct sshkey *server_host_key = NULL; @@ -165,10 +163,6 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt) (r = sshkey_from_blob(server_host_key_blob, sbloblen, &server_host_key)) != 0) goto out; - if (server_host_key->type != kex->hostkey_type) { - r = SSH_ERR_KEY_TYPE_MISMATCH; - goto out; - } if (server_host_key->type != kex->hostkey_type || (kex->hostkey_type == KEY_ECDSA && server_host_key->ecdsa_nid != kex->hostkey_nid)) { diff --git a/kexgexs.c b/kexgexs.c index 449603592cc6..c5dd00578a33 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.30 2016/09/12 01:22:38 deraadt Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.31 2017/05/30 14:23:52 markus Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -54,8 +54,8 @@ #include "sshbuf.h" #include "misc.h" -static int input_kex_dh_gex_request(int, u_int32_t, void *); -static int input_kex_dh_gex_init(int, u_int32_t, void *); +static int input_kex_dh_gex_request(int, u_int32_t, struct ssh *); +static int input_kex_dh_gex_init(int, u_int32_t, struct ssh *); int kexgex_server(struct ssh *ssh) @@ -67,9 +67,8 @@ kexgex_server(struct ssh *ssh) } static int -input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt) +input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; int r; u_int min = 0, max = 0, nbits = 0; @@ -120,9 +119,8 @@ input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt) } static int -input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt) +input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) { - struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; struct sshkey *server_host_public, *server_host_private; diff --git a/key.c b/key.c index 93f4ccb24f45..6e338c495bbb 100644 --- a/key.c +++ b/key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.130 2016/05/02 09:36:42 djm Exp $ */ +/* $OpenBSD: key.c,v 1.131 2017/05/30 14:16:41 markus Exp $ */ /* * placed in the public domain */ @@ -20,68 +20,6 @@ #include "log.h" #include "authfile.h" -void -key_add_private(Key *k) -{ - int r; - - if ((r = sshkey_add_private(k)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); -} - -Key * -key_new_private(int type) -{ - Key *ret = NULL; - - if ((ret = sshkey_new_private(type)) == NULL) - fatal("%s: failed", __func__); - return ret; -} - -int -key_read(Key *ret, char **cpp) -{ - return sshkey_read(ret, cpp) == 0 ? 1 : -1; -} - -int -key_write(const Key *key, FILE *f) -{ - return sshkey_write(key, f) == 0 ? 1 : 0; -} - -Key * -key_generate(int type, u_int bits) -{ - int r; - Key *ret = NULL; - - if ((r = sshkey_generate(type, bits, &ret)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); - return ret; -} - -void -key_cert_copy(const Key *from_key, Key *to_key) -{ - int r; - - if ((r = sshkey_cert_copy(from_key, to_key)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); -} - -Key * -key_from_private(const Key *k) -{ - int r; - Key *ret = NULL; - - if ((r = sshkey_from_private(k, &ret)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); - return ret; -} - static void fatal_on_fatal_errors(int r, const char *func, int extra_fatal) { @@ -183,19 +121,6 @@ key_demote(const Key *k) return ret; } -int -key_to_certified(Key *k) -{ - int r; - - if ((r = sshkey_to_certified(k)) != 0) { - fatal_on_fatal_errors(r, __func__, 0); - error("%s: %s", __func__, ssh_err(r)); - return -1; - } - return 0; -} - int key_drop_cert(Key *k) { @@ -209,19 +134,6 @@ key_drop_cert(Key *k) return 0; } -int -key_certify(Key *k, Key *ca) -{ - int r; - - if ((r = sshkey_certify(k, ca, NULL)) != 0) { - fatal_on_fatal_errors(r, __func__, 0); - error("%s: %s", __func__, ssh_err(r)); - return -1; - } - return 0; -} - int key_cert_check_authority(const Key *k, int want_host, int require_principal, const char *name, const char **reason) @@ -237,88 +149,8 @@ key_cert_check_authority(const Key *k, int want_host, int require_principal, return 0; } -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) -int -key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) -{ - int r; - - if ((r = sshkey_ec_validate_public(group, public)) != 0) { - fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); - error("%s: %s", __func__, ssh_err(r)); - return -1; - } - return 0; -} - -int -key_ec_validate_private(const EC_KEY *key) -{ - int r; - - if ((r = sshkey_ec_validate_private(key)) != 0) { - fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); - error("%s: %s", __func__, ssh_err(r)); - return -1; - } - return 0; -} -#endif /* WITH_OPENSSL */ - -void -key_private_serialize(const Key *key, struct sshbuf *b) -{ - int r; - - if ((r = sshkey_private_serialize(key, b)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); -} - -Key * -key_private_deserialize(struct sshbuf *blob) -{ - int r; - Key *ret = NULL; - - if ((r = sshkey_private_deserialize(blob, &ret)) != 0) { - fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); - error("%s: %s", __func__, ssh_err(r)); - return NULL; - } - return ret; -} - /* authfile.c */ -int -key_save_private(Key *key, const char *filename, const char *passphrase, - const char *comment, int force_new_format, const char *new_format_cipher, - int new_format_rounds) -{ - int r; - - if ((r = sshkey_save_private(key, filename, passphrase, comment, - force_new_format, new_format_cipher, new_format_rounds)) != 0) { - fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); - error("%s: %s", __func__, ssh_err(r)); - return 0; - } - return 1; -} - -int -key_load_file(int fd, const char *filename, struct sshbuf *blob) -{ - int r; - - if ((r = sshkey_load_file(fd, blob)) != 0) { - fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR); - error("%s: %s", __func__, ssh_err(r)); - return 0; - } - return 1; -} - Key * key_load_cert(const char *filename) { @@ -417,10 +249,3 @@ key_load_private_type(int type, const char *filename, const char *passphrase, } return ret; } - -int -key_perm_ok(int fd, const char *filename) -{ - return sshkey_perm_ok(fd, filename) == 0 ? 1 : 0; -} - diff --git a/key.h b/key.h index 2e501a9f492f..a14f370376c0 100644 --- a/key.h +++ b/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.50 2016/09/12 23:31:27 djm Exp $ */ +/* $OpenBSD: key.h,v 1.51 2017/05/30 14:16:41 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -35,51 +35,24 @@ typedef struct sshkey Key; #define fp_rep sshkey_fp_rep #ifndef SSH_KEY_NO_DEFINE -#define key_new sshkey_new #define key_free sshkey_free #define key_equal_public sshkey_equal_public #define key_equal sshkey_equal #define key_type sshkey_type -#define key_cert_type sshkey_cert_type #define key_ssh_name sshkey_ssh_name #define key_ssh_name_plain sshkey_ssh_name_plain #define key_type_from_name sshkey_type_from_name -#define key_ecdsa_nid_from_name sshkey_ecdsa_nid_from_name -#define key_type_is_cert sshkey_type_is_cert -#define key_size sshkey_size -#define key_ecdsa_bits_to_nid sshkey_ecdsa_bits_to_nid -#define key_ecdsa_key_to_nid sshkey_ecdsa_key_to_nid #define key_is_cert sshkey_is_cert #define key_type_plain sshkey_type_plain -#define key_curve_name_to_nid sshkey_curve_name_to_nid -#define key_curve_nid_to_bits sshkey_curve_nid_to_bits -#define key_curve_nid_to_name sshkey_curve_nid_to_name -#define key_ec_nid_to_hash_alg sshkey_ec_nid_to_hash_alg -#define key_dump_ec_point sshkey_dump_ec_point -#define key_dump_ec_key sshkey_dump_ec_key #endif -void key_add_private(Key *); -Key *key_new_private(int); void key_free(Key *); Key *key_demote(const Key *); -int key_write(const Key *, FILE *); -int key_read(Key *, char **); -Key *key_generate(int, u_int); -Key *key_from_private(const Key *); -int key_to_certified(Key *); int key_drop_cert(Key *); -int key_certify(Key *, Key *); -void key_cert_copy(const Key *, Key *); int key_cert_check_authority(const Key *, int, int, const char *, const char **); -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) -int key_ec_validate_public(const EC_GROUP *, const EC_POINT *); -int key_ec_validate_private(const EC_KEY *); -#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */ - Key *key_from_blob(const u_char *, u_int); int key_to_blob(const Key *, u_char **, u_int *); @@ -87,18 +60,11 @@ int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int, const char *); int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); -void key_private_serialize(const Key *, struct sshbuf *); -Key *key_private_deserialize(struct sshbuf *); - /* authfile.c */ -int key_save_private(Key *, const char *, const char *, const char *, - int, const char *, int); -int key_load_file(int, const char *, struct sshbuf *); Key *key_load_cert(const char *); Key *key_load_public(const char *, char **); Key *key_load_private(const char *, const char *, char **); Key *key_load_private_cert(int, const char *, const char *, int *); Key *key_load_private_type(int, const char *, const char *, char **, int *); -int key_perm_ok(int, const char *); #endif diff --git a/krl.c b/krl.c index 3f28178b7b3c..086fc20e5933 100644 --- a/krl.c +++ b/krl.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: krl.c,v 1.39 2017/03/10 07:18:32 dtucker Exp $ */ +/* $OpenBSD: krl.c,v 1.40 2017/05/31 09:15:42 deraadt Exp $ */ #include "includes.h" @@ -1026,7 +1026,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, } } /* Record keys used to sign the KRL */ - tmp_ca_used = reallocarray(ca_used, nca_used + 1, + tmp_ca_used = recallocarray(ca_used, nca_used, nca_used + 1, sizeof(*ca_used)); if (tmp_ca_used == NULL) { r = SSH_ERR_ALLOC_FAIL; diff --git a/log.c b/log.c index d0f86cf6fb40..99450dd125c8 100644 --- a/log.c +++ b/log.c @@ -1,4 +1,4 @@ -/* $OpenBSD: log.c,v 1.49 2017/03/10 03:15:58 djm Exp $ */ +/* $OpenBSD: log.c,v 1.50 2017/05/17 01:24:17 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -256,18 +256,7 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) argv0 = av0; - switch (level) { - case SYSLOG_LEVEL_QUIET: - case SYSLOG_LEVEL_FATAL: - case SYSLOG_LEVEL_ERROR: - case SYSLOG_LEVEL_INFO: - case SYSLOG_LEVEL_VERBOSE: - case SYSLOG_LEVEL_DEBUG1: - case SYSLOG_LEVEL_DEBUG2: - case SYSLOG_LEVEL_DEBUG3: - log_level = level; - break; - default: + if (log_change_level(level) != 0) { fprintf(stderr, "Unrecognized internal syslog level code %d\n", (int) level); exit(1); @@ -340,13 +329,27 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) #endif } -void +int log_change_level(LogLevel new_log_level) { /* no-op if log_init has not been called */ if (argv0 == NULL) - return; - log_init(argv0, new_log_level, log_facility, log_on_stderr); + return 0; + + switch (new_log_level) { + case SYSLOG_LEVEL_QUIET: + case SYSLOG_LEVEL_FATAL: + case SYSLOG_LEVEL_ERROR: + case SYSLOG_LEVEL_INFO: + case SYSLOG_LEVEL_VERBOSE: + case SYSLOG_LEVEL_DEBUG1: + case SYSLOG_LEVEL_DEBUG2: + case SYSLOG_LEVEL_DEBUG3: + log_level = new_log_level; + return 0; + default: + return -1; + } } int diff --git a/log.h b/log.h index 434b7c81a97c..78221046c26a 100644 --- a/log.h +++ b/log.h @@ -1,4 +1,4 @@ -/* $OpenBSD: log.h,v 1.21 2016/07/15 05:01:58 dtucker Exp $ */ +/* $OpenBSD: log.h,v 1.22 2017/05/17 01:24:17 djm Exp $ */ /* * Author: Tatu Ylonen @@ -49,7 +49,7 @@ typedef enum { typedef void (log_handler_fn)(LogLevel, const char *, void *); void log_init(char *, LogLevel, SyslogFacility, int); -void log_change_level(LogLevel); +int log_change_level(LogLevel); int log_is_on_stderr(void); void log_redirect_stderr_to(const char *); diff --git a/mac.c b/mac.c index 5ba7fae19539..51dc11d76b92 100644 --- a/mac.c +++ b/mac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mac.c,v 1.33 2016/07/08 03:44:42 djm Exp $ */ +/* $OpenBSD: mac.c,v 1.34 2017/05/08 22:57:38 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -64,10 +64,6 @@ static const struct macalg macs[] = { #endif { "hmac-md5", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 0 }, { "hmac-md5-96", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 0 }, -#ifdef HAVE_EVP_RIPEMD160 - { "hmac-ripemd160", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 }, - { "hmac-ripemd160@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 }, -#endif { "umac-64@openssh.com", SSH_UMAC, 0, 0, 128, 64, 0 }, { "umac-128@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 0 }, @@ -80,9 +76,6 @@ static const struct macalg macs[] = { #endif { "hmac-md5-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 1 }, { "hmac-md5-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 1 }, -#ifdef HAVE_EVP_RIPEMD160 - { "hmac-ripemd160-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 1 }, -#endif { "umac-64-etm@openssh.com", SSH_UMAC, 0, 0, 128, 64, 1 }, { "umac-128-etm@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 1 }, diff --git a/md-sha256.c b/md-sha256.c deleted file mode 100644 index 8c1b3b92da9b..000000000000 --- a/md-sha256.c +++ /dev/null @@ -1,86 +0,0 @@ -/* $OpenBSD: md-sha256.c,v 1.5 2006/08/03 03:34:42 deraadt Exp $ */ -/* - * Copyright (c) 2005 Damien Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* EVP wrapper for SHA256 */ - -#include "includes.h" - -#include -#include - -#if !defined(HAVE_EVP_SHA256) && (OPENSSL_VERSION_NUMBER >= 0x00907000L) - -#include -#include -#ifdef HAVE_SHA256_UPDATE -# ifdef HAVE_SHA2_H -# include -# elif defined(HAVE_CRYPTO_SHA2_H) -# include -# endif -#endif - -const EVP_MD *evp_ssh_sha256(void); - -static int -ssh_sha256_init(EVP_MD_CTX *ctxt) -{ - SHA256_Init(ctxt->md_data); - return (1); -} - -static int -ssh_sha256_update(EVP_MD_CTX *ctxt, const void *data, unsigned long len) -{ - SHA256_Update(ctxt->md_data, data, len); - return (1); -} - -static int -ssh_sha256_final(EVP_MD_CTX *ctxt, unsigned char *digest) -{ - SHA256_Final(digest, ctxt->md_data); - return (1); -} - -static int -ssh_sha256_cleanup(EVP_MD_CTX *ctxt) -{ - memset(ctxt->md_data, 0, sizeof(SHA256_CTX)); - return (1); -} - -const EVP_MD * -evp_ssh_sha256(void) -{ - static EVP_MD ssh_sha256; - - memset(&ssh_sha256, 0, sizeof(ssh_sha256)); - ssh_sha256.type = NID_undef; - ssh_sha256.md_size = SHA256_DIGEST_LENGTH; - ssh_sha256.init = ssh_sha256_init; - ssh_sha256.update = ssh_sha256_update; - ssh_sha256.final = ssh_sha256_final; - ssh_sha256.cleanup = ssh_sha256_cleanup; - ssh_sha256.block_size = SHA256_BLOCK_LENGTH; - ssh_sha256.ctx_size = sizeof(SHA256_CTX); - - return (&ssh_sha256); -} - -#endif /* !defined(HAVE_EVP_SHA256) && (OPENSSL_VERSION_NUMBER >= 0x00907000L) */ - diff --git a/misc.c b/misc.c index cfd32729ac7a..05950a471246 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.109 2017/03/14 00:55:37 dtucker Exp $ */ +/* $OpenBSD: misc.c,v 1.113 2017/08/18 05:48:04 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005,2006 Damien Miller. All rights reserved. @@ -29,10 +29,16 @@ #include #include #include +#include #include +#include #include #include +#ifdef HAVE_LIBGEN_H +# include +#endif +#include #include #include #include @@ -61,6 +67,10 @@ #include "misc.h" #include "log.h" #include "ssh.h" +#include "sshbuf.h" +#include "ssherr.h" +#include "uidswap.h" +#include "platform.h" /* remove newline at end of string */ char * @@ -539,7 +549,7 @@ addargs(arglist *args, char *fmt, ...) } else if (args->num+2 >= nalloc) nalloc *= 2; - args->list = xreallocarray(args->list, nalloc, sizeof(char *)); + args->list = xrecallocarray(args->list, args->nalloc, nalloc, sizeof(char *)); args->nalloc = nalloc; args->list[args->num++] = cp; args->list[args->num] = NULL; @@ -1085,6 +1095,7 @@ static const struct { const char *name; int value; } ipqos[] = { + { "none", INT_MAX }, /* can't use 0 here; that's CS0 */ { "af11", IPTOS_DSCP_AF11 }, { "af12", IPTOS_DSCP_AF12 }, { "af13", IPTOS_DSCP_AF13 }, @@ -1274,3 +1285,461 @@ daemonized(void) debug3("already daemonized"); return 1; } + + +/* + * Splits 's' into an argument vector. Handles quoted string and basic + * escape characters (\\, \", \'). Caller must free the argument vector + * and its members. + */ +int +argv_split(const char *s, int *argcp, char ***argvp) +{ + int r = SSH_ERR_INTERNAL_ERROR; + int argc = 0, quote, i, j; + char *arg, **argv = xcalloc(1, sizeof(*argv)); + + *argvp = NULL; + *argcp = 0; + + for (i = 0; s[i] != '\0'; i++) { + /* Skip leading whitespace */ + if (s[i] == ' ' || s[i] == '\t') + continue; + + /* Start of a token */ + quote = 0; + if (s[i] == '\\' && + (s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\')) + i++; + else if (s[i] == '\'' || s[i] == '"') + quote = s[i++]; + + argv = xreallocarray(argv, (argc + 2), sizeof(*argv)); + arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1); + argv[argc] = NULL; + + /* Copy the token in, removing escapes */ + for (j = 0; s[i] != '\0'; i++) { + if (s[i] == '\\') { + if (s[i + 1] == '\'' || + s[i + 1] == '\"' || + s[i + 1] == '\\') { + i++; /* Skip '\' */ + arg[j++] = s[i]; + } else { + /* Unrecognised escape */ + arg[j++] = s[i]; + } + } else if (quote == 0 && (s[i] == ' ' || s[i] == '\t')) + break; /* done */ + else if (quote != 0 && s[i] == quote) + break; /* done */ + else + arg[j++] = s[i]; + } + if (s[i] == '\0') { + if (quote != 0) { + /* Ran out of string looking for close quote */ + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + break; + } + } + /* Success */ + *argcp = argc; + *argvp = argv; + argc = 0; + argv = NULL; + r = 0; + out: + if (argc != 0 && argv != NULL) { + for (i = 0; i < argc; i++) + free(argv[i]); + free(argv); + } + return r; +} + +/* + * Reassemble an argument vector into a string, quoting and escaping as + * necessary. Caller must free returned string. + */ +char * +argv_assemble(int argc, char **argv) +{ + int i, j, ws, r; + char c, *ret; + struct sshbuf *buf, *arg; + + if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + + for (i = 0; i < argc; i++) { + ws = 0; + sshbuf_reset(arg); + for (j = 0; argv[i][j] != '\0'; j++) { + r = 0; + c = argv[i][j]; + switch (c) { + case ' ': + case '\t': + ws = 1; + r = sshbuf_put_u8(arg, c); + break; + case '\\': + case '\'': + case '"': + if ((r = sshbuf_put_u8(arg, '\\')) != 0) + break; + /* FALLTHROUGH */ + default: + r = sshbuf_put_u8(arg, c); + break; + } + if (r != 0) + fatal("%s: sshbuf_put_u8: %s", + __func__, ssh_err(r)); + } + if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) || + (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) || + (r = sshbuf_putb(buf, arg)) != 0 || + (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0)) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + } + if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL) + fatal("%s: malloc failed", __func__); + memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf)); + ret[sshbuf_len(buf)] = '\0'; + sshbuf_free(buf); + sshbuf_free(arg); + return ret; +} + +/* + * Runs command in a subprocess wuth a minimal environment. + * Returns pid on success, 0 on failure. + * The child stdout and stderr maybe captured, left attached or sent to + * /dev/null depending on the contents of flags. + * "tag" is prepended to log messages. + * NB. "command" is only used for logging; the actual command executed is + * av[0]. + */ +pid_t +subprocess(const char *tag, struct passwd *pw, const char *command, + int ac, char **av, FILE **child, u_int flags) +{ + FILE *f = NULL; + struct stat st; + int fd, devnull, p[2], i; + pid_t pid; + char *cp, errmsg[512]; + u_int envsize; + char **child_env; + + if (child != NULL) + *child = NULL; + + debug3("%s: %s command \"%s\" running as %s (flags 0x%x)", __func__, + tag, command, pw->pw_name, flags); + + /* Check consistency */ + if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 && + (flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) { + error("%s: inconsistent flags", __func__); + return 0; + } + if (((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) != (child == NULL)) { + error("%s: inconsistent flags/output", __func__); + return 0; + } + + /* + * If executing an explicit binary, then verify the it exists + * and appears safe-ish to execute + */ + if (*av[0] != '/') { + error("%s path is not absolute", tag); + return 0; + } + temporarily_use_uid(pw); + if (stat(av[0], &st) < 0) { + error("Could not stat %s \"%s\": %s", tag, + av[0], strerror(errno)); + restore_uid(); + return 0; + } + if (safe_path(av[0], &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) { + error("Unsafe %s \"%s\": %s", tag, av[0], errmsg); + restore_uid(); + return 0; + } + /* Prepare to keep the child's stdout if requested */ + if (pipe(p) != 0) { + error("%s: pipe: %s", tag, strerror(errno)); + restore_uid(); + return 0; + } + restore_uid(); + + switch ((pid = fork())) { + case -1: /* error */ + error("%s: fork: %s", tag, strerror(errno)); + close(p[0]); + close(p[1]); + return 0; + case 0: /* child */ + /* Prepare a minimal environment for the child. */ + envsize = 5; + child_env = xcalloc(sizeof(*child_env), envsize); + child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH); + child_set_env(&child_env, &envsize, "USER", pw->pw_name); + child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name); + child_set_env(&child_env, &envsize, "HOME", pw->pw_dir); + if ((cp = getenv("LANG")) != NULL) + child_set_env(&child_env, &envsize, "LANG", cp); + + for (i = 0; i < NSIG; i++) + signal(i, SIG_DFL); + + if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { + error("%s: open %s: %s", tag, _PATH_DEVNULL, + strerror(errno)); + _exit(1); + } + if (dup2(devnull, STDIN_FILENO) == -1) { + error("%s: dup2: %s", tag, strerror(errno)); + _exit(1); + } + + /* Set up stdout as requested; leave stderr in place for now. */ + fd = -1; + if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) + fd = p[1]; + else if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0) + fd = devnull; + if (fd != -1 && dup2(fd, STDOUT_FILENO) == -1) { + error("%s: dup2: %s", tag, strerror(errno)); + _exit(1); + } + closefrom(STDERR_FILENO + 1); + + /* Don't use permanently_set_uid() here to avoid fatal() */ + if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) { + error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid, + strerror(errno)); + _exit(1); + } + if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) { + error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid, + strerror(errno)); + _exit(1); + } + /* stdin is pointed to /dev/null at this point */ + if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 && + dup2(STDIN_FILENO, STDERR_FILENO) == -1) { + error("%s: dup2: %s", tag, strerror(errno)); + _exit(1); + } + + execve(av[0], av, child_env); + error("%s exec \"%s\": %s", tag, command, strerror(errno)); + _exit(127); + default: /* parent */ + break; + } + + close(p[1]); + if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) + close(p[0]); + else if ((f = fdopen(p[0], "r")) == NULL) { + error("%s: fdopen: %s", tag, strerror(errno)); + close(p[0]); + /* Don't leave zombie child */ + kill(pid, SIGTERM); + while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) + ; + return 0; + } + /* Success */ + debug3("%s: %s pid %ld", __func__, tag, (long)pid); + if (child != NULL) + *child = f; + return pid; +} + +/* Returns 0 if pid exited cleanly, non-zero otherwise */ +int +exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet) +{ + int status; + + while (waitpid(pid, &status, 0) == -1) { + if (errno != EINTR) { + error("%s: waitpid: %s", tag, strerror(errno)); + return -1; + } + } + if (WIFSIGNALED(status)) { + error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status)); + return -1; + } else if (WEXITSTATUS(status) != 0) { + do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO, + "%s %s failed, status %d", tag, cmd, WEXITSTATUS(status)); + return -1; + } + return 0; +} + +/* + * Check a given path for security. This is defined as all components + * of the path to the file must be owned by either the owner of + * of the file or root and no directories must be group or world writable. + * + * XXX Should any specific check be done for sym links ? + * + * Takes a file name, its stat information (preferably from fstat() to + * avoid races), the uid of the expected owner, their home directory and an + * error buffer plus max size as arguments. + * + * Returns 0 on success and -1 on failure + */ +int +safe_path(const char *name, struct stat *stp, const char *pw_dir, + uid_t uid, char *err, size_t errlen) +{ + char buf[PATH_MAX], homedir[PATH_MAX]; + char *cp; + int comparehome = 0; + struct stat st; + + if (realpath(name, buf) == NULL) { + snprintf(err, errlen, "realpath %s failed: %s", name, + strerror(errno)); + return -1; + } + if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL) + comparehome = 1; + + if (!S_ISREG(stp->st_mode)) { + snprintf(err, errlen, "%s is not a regular file", buf); + return -1; + } + if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || + (stp->st_mode & 022) != 0) { + snprintf(err, errlen, "bad ownership or modes for file %s", + buf); + return -1; + } + + /* for each component of the canonical path, walking upwards */ + for (;;) { + if ((cp = dirname(buf)) == NULL) { + snprintf(err, errlen, "dirname() failed"); + return -1; + } + strlcpy(buf, cp, sizeof(buf)); + + if (stat(buf, &st) < 0 || + (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || + (st.st_mode & 022) != 0) { + snprintf(err, errlen, + "bad ownership or modes for directory %s", buf); + return -1; + } + + /* If are past the homedir then we can stop */ + if (comparehome && strcmp(homedir, buf) == 0) + break; + + /* + * dirname should always complete with a "/" path, + * but we can be paranoid and check for "." too + */ + if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) + break; + } + return 0; +} + +/* + * Version of safe_path() that accepts an open file descriptor to + * avoid races. + * + * Returns 0 on success and -1 on failure + */ +int +safe_path_fd(int fd, const char *file, struct passwd *pw, + char *err, size_t errlen) +{ + struct stat st; + + /* check the open file to avoid races */ + if (fstat(fd, &st) < 0) { + snprintf(err, errlen, "cannot stat file %s: %s", + file, strerror(errno)); + return -1; + } + return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); +} + +/* + * Sets the value of the given variable in the environment. If the variable + * already exists, its value is overridden. + */ +void +child_set_env(char ***envp, u_int *envsizep, const char *name, + const char *value) +{ + char **env; + u_int envsize; + u_int i, namelen; + + if (strchr(name, '=') != NULL) { + error("Invalid environment variable \"%.100s\"", name); + return; + } + + /* + * If we're passed an uninitialized list, allocate a single null + * entry before continuing. + */ + if (*envp == NULL && *envsizep == 0) { + *envp = xmalloc(sizeof(char *)); + *envp[0] = NULL; + *envsizep = 1; + } + + /* + * Find the slot where the value should be stored. If the variable + * already exists, we reuse the slot; otherwise we append a new slot + * at the end of the array, expanding if necessary. + */ + env = *envp; + namelen = strlen(name); + for (i = 0; env[i]; i++) + if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=') + break; + if (env[i]) { + /* Reuse the slot. */ + free(env[i]); + } else { + /* New variable. Expand if necessary. */ + envsize = *envsizep; + if (i >= envsize - 1) { + if (envsize >= 1000) + fatal("child_set_env: too many env vars"); + envsize += 50; + env = (*envp) = xreallocarray(env, envsize, sizeof(char *)); + *envsizep = envsize; + } + /* Need to set the NULL pointer at end of array beyond the new slot. */ + env[i + 1] = NULL; + } + + /* Allocate space and format the variable in the appropriate slot. */ + env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1); + snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value); +} + diff --git a/misc.h b/misc.h index c242f9011f59..153d11375bf5 100644 --- a/misc.h +++ b/misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.61 2016/11/30 00:28:31 dtucker Exp $ */ +/* $OpenBSD: misc.h,v 1.63 2017/08/18 05:48:04 djm Exp $ */ /* * Author: Tatu Ylonen @@ -16,6 +16,7 @@ #define _MISC_H #include +#include /* Data structure for representing a forwarding request. */ struct Forward { @@ -132,6 +133,25 @@ int parse_ipqos(const char *); const char *iptos2str(int); void mktemp_proto(char *, size_t); +void child_set_env(char ***envp, u_int *envsizep, const char *name, + const char *value); + +int argv_split(const char *, int *, char ***); +char *argv_assemble(int, char **argv); +int exited_cleanly(pid_t, const char *, const char *, int); + +#define SSH_SUBPROCESS_STDOUT_DISCARD (1) /* Discard stdout */ +#define SSH_SUBPROCESS_STDOUT_CAPTURE (1<<1) /* Redirect stdout */ +#define SSH_SUBPROCESS_STDERR_DISCARD (1<<2) /* Discard stderr */ +pid_t subprocess(const char *, struct passwd *, + const char *, int, char **, FILE **, u_int flags); + +struct stat; +int safe_path(const char *, struct stat *, const char *, uid_t, + char *, size_t); +int safe_path_fd(int, const char *, struct passwd *, + char *err, size_t errlen); + /* readpass.c */ #define RP_ECHO 0x0001 diff --git a/moduli.0 b/moduli.0 index dd762af85576..e319015b28a7 100644 --- a/moduli.0 +++ b/moduli.0 @@ -71,4 +71,4 @@ STANDARDS the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006, 2006. -OpenBSD 6.0 September 26, 2012 OpenBSD 6.0 +OpenBSD 6.2 September 26, 2012 OpenBSD 6.2 diff --git a/monitor.c b/monitor.c index 96d22b7e40e9..f517da482ce5 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.167 2017/02/03 23:05:57 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.174 2017/10/02 19:33:20 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -308,6 +308,8 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) partial = 0; auth_method = "unknown"; auth_submethod = NULL; + auth2_authctxt_reset_info(authctxt); + authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); /* Special handling for multiple required authentications */ @@ -347,6 +349,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) auth_method, auth_submethod); if (!partial && !authenticated) authctxt->failures++; + if (authenticated || partial) { + auth2_update_session_info(authctxt, + auth_method, auth_submethod); + } } } @@ -754,10 +760,12 @@ mm_answer_pwnamallow(int sock, Buffer *m) for (i = 0; i < options.nx; i++) \ buffer_put_cstring(m, options.x[i]); \ } while (0) +#define M_CP_STRARRAYOPT_ALLOC(x, nx) M_CP_STRARRAYOPT(x, nx) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); #undef M_CP_STROPT #undef M_CP_STRARRAYOPT +#undef M_CP_STRARRAYOPT_ALLOC /* Create valid auth method lists */ if (auth2_setup_methods_lists(authctxt) != 0) { @@ -1119,7 +1127,7 @@ mm_answer_pam_free_ctx(int sock, Buffer *m) int mm_answer_keyallowed(int sock, Buffer *m) { - Key *key; + struct sshkey *key; char *cuser, *chost; u_char *blob; u_int bloblen, pubkey_auth_attempt; @@ -1147,12 +1155,11 @@ mm_answer_keyallowed(int sock, Buffer *m) switch (type) { case MM_USERKEY: allowed = options.pubkey_authentication && - !auth2_userkey_already_used(authctxt, key) && + !auth2_key_already_used(authctxt, key) && match_pattern_list(sshkey_ssh_name(key), options.pubkey_key_types, 0) == 1 && user_key_allowed(authctxt->pw, key, pubkey_auth_attempt); - pubkey_auth_info(authctxt, key, NULL); auth_method = "publickey"; if (options.pubkey_authentication && (!pubkey_auth_attempt || allowed != 1)) @@ -1160,11 +1167,12 @@ mm_answer_keyallowed(int sock, Buffer *m) break; case MM_HOSTKEY: allowed = options.hostbased_authentication && + !auth2_key_already_used(authctxt, key) && match_pattern_list(sshkey_ssh_name(key), options.hostbased_key_types, 0) == 1 && hostbased_key_allowed(authctxt->pw, cuser, chost, key); - pubkey_auth_info(authctxt, key, + auth2_record_info(authctxt, "client user \"%.100s\", client host \"%.100s\"", cuser, chost); auth_method = "hostbased"; @@ -1175,11 +1183,10 @@ mm_answer_keyallowed(int sock, Buffer *m) } } - debug3("%s: key %p is %s", - __func__, key, allowed ? "allowed" : "not allowed"); + debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed"); - if (key != NULL) - key_free(key); + auth2_record_key(authctxt, 0, key); + sshkey_free(key); /* clear temporarily storage (used by verify) */ monitor_reset_key_state(); @@ -1330,33 +1337,35 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, } int -mm_answer_keyverify(int sock, Buffer *m) +mm_answer_keyverify(int sock, struct sshbuf *m) { - Key *key; + struct sshkey *key; u_char *signature, *data, *blob; - u_int signaturelen, datalen, bloblen; - int verified = 0; - int valid_data = 0; + size_t signaturelen, datalen, bloblen; + int r, ret, valid_data = 0, encoded_ret; - blob = buffer_get_string(m, &bloblen); - signature = buffer_get_string(m, &signaturelen); - data = buffer_get_string(m, &datalen); + if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || + (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || + (r = sshbuf_get_string(m, &data, &datalen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) fatal("%s: bad key, not previously allowed", __func__); - key = key_from_blob(blob, bloblen); - if (key == NULL) - fatal("%s: bad public key blob", __func__); + /* XXX use sshkey_froms here; need to change key_blob, etc. */ + if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) + fatal("%s: bad public key blob: %s", __func__, ssh_err(r)); switch (key_blobtype) { case MM_USERKEY: valid_data = monitor_valid_userblob(data, datalen); + auth_method = "publickey"; break; case MM_HOSTKEY: valid_data = monitor_valid_hostbasedblob(data, datalen, hostbased_cuser, hostbased_chost); + auth_method = "hostbased"; break; default: valid_data = 0; @@ -1365,29 +1374,28 @@ mm_answer_keyverify(int sock, Buffer *m) if (!valid_data) fatal("%s: bad signature data blob", __func__); - verified = key_verify(key, signature, signaturelen, data, datalen); - debug3("%s: key %p signature %s", - __func__, key, (verified == 1) ? "verified" : "unverified"); - - /* If auth was successful then record key to ensure it isn't reused */ - if (verified == 1 && key_blobtype == MM_USERKEY) - auth2_record_userkey(authctxt, key); - else - key_free(key); + ret = sshkey_verify(key, signature, signaturelen, data, datalen, + active_state->compat); + debug3("%s: %s %p signature %s", __func__, auth_method, key, + (ret == 0) ? "verified" : "unverified"); + auth2_record_key(authctxt, ret == 0, key); free(blob); free(signature); free(data); - auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; - monitor_reset_key_state(); - buffer_clear(m); - buffer_put_int(m, verified); + sshkey_free(key); + sshbuf_reset(m); + + /* encode ret != 0 as positive integer, since we're sending u32 */ + encoded_ret = (ret != 0); + if ((r = sshbuf_put_u32(m, encoded_ret)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); - return (verified == 1); + return ret == 0; } static void @@ -1513,13 +1521,14 @@ mm_answer_pty_cleanup(int sock, Buffer *m) int mm_answer_term(int sock, Buffer *req) { + struct ssh *ssh = active_state; /* XXX */ extern struct monitor *pmonitor; int res, status; debug3("%s: tearing down sessions", __func__); /* The child is terminating */ - session_destroy_all(&mm_session_close); + session_destroy_all(ssh, &mm_session_close); #ifdef USE_PAM if (options.use_pam) @@ -1578,6 +1587,17 @@ mm_answer_audit_command(int socket, Buffer *m) } #endif /* SSH_AUDIT_EVENTS */ +void +monitor_clear_keystate(struct monitor *pmonitor) +{ + struct ssh *ssh = active_state; /* XXX */ + + ssh_clear_newkeys(ssh, MODE_IN); + ssh_clear_newkeys(ssh, MODE_OUT); + sshbuf_free(child_state); + child_state = NULL; +} + void monitor_apply_keystate(struct monitor *pmonitor) { @@ -1639,9 +1659,18 @@ static void monitor_openfds(struct monitor *mon, int do_logfds) { int pair[2]; +#ifdef SO_ZEROIZE + int on = 1; +#endif if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) fatal("%s: socketpair: %s", __func__, strerror(errno)); +#ifdef SO_ZEROIZE + if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0) + error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno)); + if (setsockopt(pair[1], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0) + error("setsockopt SO_ZEROIZE(1): %.100s", strerror(errno)); +#endif FD_CLOSEONEXEC(pair[0]); FD_CLOSEONEXEC(pair[1]); mon->m_recvfd = pair[0]; @@ -1774,6 +1803,7 @@ int mm_answer_gss_userok(int sock, Buffer *m) { int authenticated; + const char *displayname; if (!options.gss_authentication) fatal("%s: GSSAPI authentication not enabled", __func__); @@ -1788,6 +1818,9 @@ mm_answer_gss_userok(int sock, Buffer *m) auth_method = "gssapi-with-mic"; + if ((displayname = ssh_gssapi_displayname()) != NULL) + auth2_record_info(authctxt, "%s", displayname); + /* Monitor loop will terminate if authenticated */ return (authenticated); } diff --git a/monitor_wrap.c b/monitor_wrap.c index 64ff928850c9..69212aaf330b 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.89 2016/08/13 17:47:41 markus Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.94 2017/10/02 19:33:20 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -216,7 +216,7 @@ mm_choose_dh(int min, int nbits, int max) #endif int -mm_key_sign(Key *key, u_char **sigp, u_int *lenp, +mm_key_sign(struct sshkey *key, u_char **sigp, u_int *lenp, const u_char *data, u_int datalen, const char *hostkey_alg) { struct kex *kex = *pmonitor->m_pkex; @@ -242,6 +242,7 @@ mm_key_sign(Key *key, u_char **sigp, u_int *lenp, struct passwd * mm_getpwnamallow(const char *username) { + struct ssh *ssh = active_state; /* XXX */ Buffer m; struct passwd *pw; u_int len, i; @@ -289,12 +290,20 @@ mm_getpwnamallow(const char *username) for (i = 0; i < newopts->nx; i++) \ newopts->x[i] = buffer_get_string(&m, NULL); \ } while (0) +#define M_CP_STRARRAYOPT_ALLOC(x, nx) do { \ + newopts->x = newopts->nx == 0 ? \ + NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \ + M_CP_STRARRAYOPT(x, nx); \ + } while (0) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); #undef M_CP_STROPT #undef M_CP_STRARRAYOPT +#undef M_CP_STRARRAYOPT_ALLOC copy_set_server_options(&options, newopts, 1); + log_change_level(options.log_level); + process_permitopen(ssh, &options); free(newopts); buffer_free(&m); @@ -374,7 +383,8 @@ mm_auth_password(Authctxt *authctxt, char *password) } int -mm_user_key_allowed(struct passwd *pw, Key *key, int pubkey_auth_attempt) +mm_user_key_allowed(struct passwd *pw, struct sshkey *key, + int pubkey_auth_attempt) { return (mm_key_allowed(MM_USERKEY, NULL, NULL, key, pubkey_auth_attempt)); @@ -382,14 +392,14 @@ mm_user_key_allowed(struct passwd *pw, Key *key, int pubkey_auth_attempt) int mm_hostbased_key_allowed(struct passwd *pw, const char *user, const char *host, - Key *key) + struct sshkey *key) { return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0)); } int mm_key_allowed(enum mm_keytype type, const char *user, const char *host, - Key *key, int pubkey_auth_attempt) + struct sshkey *key, int pubkey_auth_attempt) { Buffer m; u_char *blob; @@ -434,12 +444,13 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host, */ int -mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) +mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, + const u_char *data, size_t datalen, u_int compat) { Buffer m; u_char *blob; u_int len; - int verified = 0; + u_int encoded_ret = 0; debug3("%s entering", __func__); @@ -458,11 +469,13 @@ mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m); - verified = buffer_get_int(&m); + encoded_ret = buffer_get_int(&m); buffer_free(&m); - return (verified); + if (encoded_ret != 0) + return SSH_ERR_SIGNATURE_INVALID; + return 0; } void diff --git a/monitor_wrap.h b/monitor_wrap.h index db5902f553ab..9e032d204b40 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.h,v 1.32 2016/09/28 16:33:07 djm Exp $ */ +/* $OpenBSD: monitor_wrap.h,v 1.35 2017/05/31 08:09:45 markus Exp $ */ /* * Copyright 2002 Niels Provos @@ -34,22 +34,24 @@ extern int use_privsep; enum mm_keytype { MM_NOKEY, MM_HOSTKEY, MM_USERKEY }; struct monitor; -struct mm_master; struct Authctxt; void mm_log_handler(LogLevel, const char *, void *); int mm_is_monitor(void); DH *mm_choose_dh(int, int, int); -int mm_key_sign(Key *, u_char **, u_int *, const u_char *, u_int, const char *); +int mm_key_sign(struct sshkey *, u_char **, u_int *, const u_char *, u_int, + const char *); void mm_inform_authserv(char *, char *); struct passwd *mm_getpwnamallow(const char *); char *mm_auth2_read_banner(void); int mm_auth_password(struct Authctxt *, char *); -int mm_key_allowed(enum mm_keytype, const char *, const char *, Key *, int); -int mm_user_key_allowed(struct passwd *, Key *, int); +int mm_key_allowed(enum mm_keytype, const char *, const char *, struct sshkey *, + int); +int mm_user_key_allowed(struct passwd *, struct sshkey *, int); int mm_hostbased_key_allowed(struct passwd *, const char *, - const char *, Key *); -int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int); + const char *, struct sshkey *); +int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, + const u_char *, size_t, u_int); #ifdef GSSAPI OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); @@ -83,6 +85,7 @@ void mm_session_pty_cleanup2(struct Session *); struct newkeys *mm_newkeys_from_blob(u_char *, int); int mm_newkeys_to_blob(int, u_char **, u_int *); +void monitor_clear_keystate(struct monitor *); void monitor_apply_keystate(struct monitor *); void mm_get_keystate(struct monitor *); void mm_send_keystate(struct monitor*); diff --git a/mux.c b/mux.c index 2d6639c5c19a..5ae4544100e2 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.64 2017/01/21 11:32:04 guenther Exp $ */ +/* $OpenBSD: mux.c,v 1.69 2017/09/20 05:19:00 dtucker Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -161,22 +161,32 @@ struct mux_master_state { #define MUX_FWD_REMOTE 2 #define MUX_FWD_DYNAMIC 3 -static void mux_session_confirm(int, int, void *); -static void mux_stdio_confirm(int, int, void *); +static void mux_session_confirm(struct ssh *, int, int, void *); +static void mux_stdio_confirm(struct ssh *, int, int, void *); -static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *); -static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *); -static int process_mux_alive_check(u_int, Channel *, Buffer *, Buffer *); -static int process_mux_terminate(u_int, Channel *, Buffer *, Buffer *); -static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *); -static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *); -static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *); -static int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *); -static int process_mux_proxy(u_int, Channel *, Buffer *, Buffer *); +static int process_mux_master_hello(struct ssh *, u_int, + Channel *, struct sshbuf *, struct sshbuf *); +static int process_mux_new_session(struct ssh *, u_int, + Channel *, struct sshbuf *, struct sshbuf *); +static int process_mux_alive_check(struct ssh *, u_int, + Channel *, struct sshbuf *, struct sshbuf *); +static int process_mux_terminate(struct ssh *, u_int, + Channel *, struct sshbuf *, struct sshbuf *); +static int process_mux_open_fwd(struct ssh *, u_int, + Channel *, struct sshbuf *, struct sshbuf *); +static int process_mux_close_fwd(struct ssh *, u_int, + Channel *, struct sshbuf *, struct sshbuf *); +static int process_mux_stdio_fwd(struct ssh *, u_int, + Channel *, struct sshbuf *, struct sshbuf *); +static int process_mux_stop_listening(struct ssh *, u_int, + Channel *, struct sshbuf *, struct sshbuf *); +static int process_mux_proxy(struct ssh *, u_int, + Channel *, struct sshbuf *, struct sshbuf *); static const struct { u_int type; - int (*handler)(u_int, Channel *, Buffer *, Buffer *); + int (*handler)(struct ssh *, u_int, Channel *, + struct sshbuf *, struct sshbuf *); } mux_master_handlers[] = { { MUX_MSG_HELLO, process_mux_master_hello }, { MUX_C_NEW_SESSION, process_mux_new_session }, @@ -193,52 +203,54 @@ static const struct { /* Cleanup callback fired on closure of mux slave _session_ channel */ /* ARGSUSED */ static void -mux_master_session_cleanup_cb(int cid, void *unused) +mux_master_session_cleanup_cb(struct ssh *ssh, int cid, void *unused) { - Channel *cc, *c = channel_by_id(cid); + Channel *cc, *c = channel_by_id(ssh, cid); debug3("%s: entering for channel %d", __func__, cid); if (c == NULL) fatal("%s: channel_by_id(%i) == NULL", __func__, cid); if (c->ctl_chan != -1) { - if ((cc = channel_by_id(c->ctl_chan)) == NULL) + if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) fatal("%s: channel %d missing control channel %d", __func__, c->self, c->ctl_chan); c->ctl_chan = -1; - cc->remote_id = -1; - chan_rcvd_oclose(cc); + cc->remote_id = 0; + cc->have_remote_id = 0; + chan_rcvd_oclose(ssh, cc); } - channel_cancel_cleanup(c->self); + channel_cancel_cleanup(ssh, c->self); } /* Cleanup callback fired on closure of mux slave _control_ channel */ /* ARGSUSED */ static void -mux_master_control_cleanup_cb(int cid, void *unused) +mux_master_control_cleanup_cb(struct ssh *ssh, int cid, void *unused) { - Channel *sc, *c = channel_by_id(cid); + Channel *sc, *c = channel_by_id(ssh, cid); debug3("%s: entering for channel %d", __func__, cid); if (c == NULL) fatal("%s: channel_by_id(%i) == NULL", __func__, cid); - if (c->remote_id != -1) { - if ((sc = channel_by_id(c->remote_id)) == NULL) - fatal("%s: channel %d missing session channel %d", + if (c->have_remote_id) { + if ((sc = channel_by_id(ssh, c->remote_id)) == NULL) + fatal("%s: channel %d missing session channel %u", __func__, c->self, c->remote_id); - c->remote_id = -1; + c->remote_id = 0; + c->have_remote_id = 0; sc->ctl_chan = -1; if (sc->type != SSH_CHANNEL_OPEN && sc->type != SSH_CHANNEL_OPENING) { debug2("%s: channel %d: not open", __func__, sc->self); - chan_mark_dead(sc); + chan_mark_dead(ssh, sc); } else { if (sc->istate == CHAN_INPUT_OPEN) - chan_read_failed(sc); + chan_read_failed(ssh, sc); if (sc->ostate == CHAN_OUTPUT_OPEN) - chan_write_failed(sc); + chan_write_failed(ssh, sc); } } - channel_cancel_cleanup(c->self); + channel_cancel_cleanup(ssh, c->self); } /* Check mux client environment variables before passing them to mux master. */ @@ -266,7 +278,8 @@ env_permitted(char *env) /* Mux master protocol message handlers */ static int -process_mux_master_hello(u_int rid, Channel *c, Buffer *m, Buffer *r) +process_mux_master_hello(struct ssh *ssh, u_int rid, + Channel *c, Buffer *m, Buffer *r) { u_int ver; struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; @@ -308,7 +321,8 @@ process_mux_master_hello(u_int rid, Channel *c, Buffer *m, Buffer *r) } static int -process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r) +process_mux_new_session(struct ssh *ssh, u_int rid, + Channel *c, Buffer *m, Buffer *r) { Channel *nc; struct mux_session_confirm_ctx *cctx; @@ -401,7 +415,7 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r) new_fd[0], new_fd[1], new_fd[2]); /* XXX support multiple child sessions in future */ - if (c->remote_id != -1) { + if (c->have_remote_id) { debug2("%s: session already open", __func__); /* prepare reply */ buffer_put_int(r, MUX_S_FAILURE); @@ -453,15 +467,16 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r) packetmax >>= 1; } - nc = channel_new("session", SSH_CHANNEL_OPENING, + nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING, new_fd[0], new_fd[1], new_fd[2], window, packetmax, CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); nc->ctl_chan = c->self; /* link session -> control channel */ c->remote_id = nc->self; /* link control -> session channel */ + c->have_remote_id = 1; if (cctx->want_tty && escape_char != 0xffffffff) { - channel_register_filter(nc->self, + channel_register_filter(ssh, nc->self, client_simple_escape_filter, NULL, client_filter_cleanup, client_new_escape_filter_ctx((int)escape_char)); @@ -470,17 +485,19 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r) debug2("%s: channel_new: %d linked to control channel %d", __func__, nc->self, nc->ctl_chan); - channel_send_open(nc->self); - channel_register_open_confirm(nc->self, mux_session_confirm, cctx); + channel_send_open(ssh, nc->self); + channel_register_open_confirm(ssh, nc->self, mux_session_confirm, cctx); c->mux_pause = 1; /* stop handling messages until open_confirm done */ - channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1); + channel_register_cleanup(ssh, nc->self, + mux_master_session_cleanup_cb, 1); /* reply is deferred, sent by mux_session_confirm */ return 0; } static int -process_mux_alive_check(u_int rid, Channel *c, Buffer *m, Buffer *r) +process_mux_alive_check(struct ssh *ssh, u_int rid, + Channel *c, Buffer *m, Buffer *r) { debug2("%s: channel %d: alive check", __func__, c->self); @@ -493,7 +510,8 @@ process_mux_alive_check(u_int rid, Channel *c, Buffer *m, Buffer *r) } static int -process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r) +process_mux_terminate(struct ssh *ssh, u_int rid, + Channel *c, Buffer *m, Buffer *r) { debug2("%s: channel %d: terminate request", __func__, c->self); @@ -582,7 +600,7 @@ compare_forward(struct Forward *a, struct Forward *b) } static void -mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) +mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) { struct mux_channel_confirm_ctx *fctx = ctxt; char *failmsg = NULL; @@ -590,7 +608,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) Channel *c; Buffer out; - if ((c = channel_by_id(fctx->cid)) == NULL) { + if ((c = channel_by_id(ssh, fctx->cid)) == NULL) { /* no channel for reply */ error("%s: unknown channel", __func__); return; @@ -616,7 +634,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) buffer_put_int(&out, MUX_S_REMOTE_PORT); buffer_put_int(&out, fctx->rid); buffer_put_int(&out, rfwd->allocated_port); - channel_update_permitted_opens(rfwd->handle, + channel_update_permitted_opens(ssh, rfwd->handle, rfwd->allocated_port); } else { buffer_put_int(&out, MUX_S_OK); @@ -625,7 +643,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) goto out; } else { if (rfwd->listen_port == 0) - channel_update_permitted_opens(rfwd->handle, -1); + channel_update_permitted_opens(ssh, rfwd->handle, -1); if (rfwd->listen_path != NULL) xasprintf(&failmsg, "remote port forwarding failed for " "listen path %s", rfwd->listen_path); @@ -651,7 +669,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) buffer_put_cstring(&out, failmsg); free(failmsg); out: - buffer_put_string(&c->output, buffer_ptr(&out), buffer_len(&out)); + buffer_put_string(c->output, buffer_ptr(&out), buffer_len(&out)); buffer_free(&out); if (c->mux_pause <= 0) fatal("%s: mux_pause %d", __func__, c->mux_pause); @@ -659,7 +677,8 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) } static int -process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) +process_mux_open_fwd(struct ssh *ssh, u_int rid, + Channel *c, Buffer *m, Buffer *r) { struct Forward fwd; char *fwd_desc = NULL; @@ -727,13 +746,16 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) fwd.listen_port); goto invalid; } - if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536) - || (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { + if ((fwd.connect_port != PORT_STREAMLOCAL && + fwd.connect_port >= 65536) || + (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && + fwd.connect_port == 0)) { logit("%s: invalid connect port %u", __func__, fwd.connect_port); goto invalid; } - if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) { + if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && + fwd.connect_path == NULL) { logit("%s: missing connect host", __func__); goto invalid; } @@ -784,7 +806,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) } if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { - if (!channel_setup_local_fwd_listener(&fwd, + if (!channel_setup_local_fwd_listener(ssh, &fwd, &options.fwd_opts)) { fail: logit("slave-requested %s failed", fwd_desc); @@ -798,7 +820,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) } else { struct mux_channel_confirm_ctx *fctx; - fwd.handle = channel_request_remote_forwarding(&fwd); + fwd.handle = channel_request_remote_forwarding(ssh, &fwd); if (fwd.handle < 0) goto fail; add_remote_forward(&options, &fwd); @@ -827,7 +849,8 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) } static int -process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) +process_mux_close_fwd(struct ssh *ssh, u_int rid, + Channel *c, Buffer *m, Buffer *r) { struct Forward fwd, *found_fwd; char *fwd_desc = NULL; @@ -908,11 +931,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) * However, for dynamic allocated listen ports we need * to use the actual listen port. */ - if (channel_request_rforward_cancel(found_fwd) == -1) + if (channel_request_rforward_cancel(ssh, found_fwd) == -1) error_reason = "port not in permitted opens"; } else { /* local and dynamic forwards */ /* Ditto */ - if (channel_cancel_lport_listener(&fwd, fwd.connect_port, + if (channel_cancel_lport_listener(ssh, &fwd, fwd.connect_port, &options.fwd_opts) == -1) error_reason = "port not found"; } @@ -942,7 +965,8 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) } static int -process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) +process_mux_stdio_fwd(struct ssh *ssh, u_int rid, + Channel *c, Buffer *m, Buffer *r) { Channel *nc; char *reserved, *chost; @@ -986,7 +1010,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) new_fd[0], new_fd[1]); /* XXX support multiple child sessions in future */ - if (c->remote_id != -1) { + if (c->have_remote_id) { debug2("%s: session already open", __func__); /* prepare reply */ buffer_put_int(r, MUX_S_FAILURE); @@ -1018,19 +1042,21 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) if (!isatty(new_fd[1])) set_nonblock(new_fd[1]); - nc = channel_connect_stdio_fwd(chost, cport, new_fd[0], new_fd[1]); + nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1]); nc->ctl_chan = c->self; /* link session -> control channel */ c->remote_id = nc->self; /* link control -> session channel */ + c->have_remote_id = 1; debug2("%s: channel_new: %d linked to control channel %d", __func__, nc->self, nc->ctl_chan); - channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1); + channel_register_cleanup(ssh, nc->self, + mux_master_session_cleanup_cb, 1); cctx = xcalloc(1, sizeof(*cctx)); cctx->rid = rid; - channel_register_open_confirm(nc->self, mux_stdio_confirm, cctx); + channel_register_open_confirm(ssh, nc->self, mux_stdio_confirm, cctx); c->mux_pause = 1; /* stop handling messages until open_confirm done */ /* reply is deferred, sent by mux_session_confirm */ @@ -1039,7 +1065,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) /* Callback on open confirmation in mux master for a mux stdio fwd session. */ static void -mux_stdio_confirm(int id, int success, void *arg) +mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) { struct mux_stdio_confirm_ctx *cctx = arg; Channel *c, *cc; @@ -1047,9 +1073,9 @@ mux_stdio_confirm(int id, int success, void *arg) if (cctx == NULL) fatal("%s: cctx == NULL", __func__); - if ((c = channel_by_id(id)) == NULL) + if ((c = channel_by_id(ssh, id)) == NULL) fatal("%s: no channel for id %d", __func__, id); - if ((cc = channel_by_id(c->ctl_chan)) == NULL) + if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) fatal("%s: channel %d lacks control channel %d", __func__, id, c->ctl_chan); @@ -1072,7 +1098,7 @@ mux_stdio_confirm(int id, int success, void *arg) done: /* Send reply */ - buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply)); + buffer_put_string(cc->output, buffer_ptr(&reply), buffer_len(&reply)); buffer_free(&reply); if (cc->mux_pause <= 0) @@ -1083,7 +1109,8 @@ mux_stdio_confirm(int id, int success, void *arg) } static int -process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) +process_mux_stop_listening(struct ssh *ssh, u_int rid, + Channel *c, Buffer *m, Buffer *r) { debug("%s: channel %d: stop listening", __func__, c->self); @@ -1100,7 +1127,7 @@ process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) } if (mux_listener_channel != NULL) { - channel_free(mux_listener_channel); + channel_free(ssh, mux_listener_channel); client_stop_mux(); free(options.control_path); options.control_path = NULL; @@ -1116,7 +1143,8 @@ process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) } static int -process_mux_proxy(u_int rid, Channel *c, Buffer *m, Buffer *r) +process_mux_proxy(struct ssh *ssh, u_int rid, + Channel *c, Buffer *m, Buffer *r) { debug("%s: channel %d: proxy request", __func__, c->self); @@ -1129,7 +1157,7 @@ process_mux_proxy(u_int rid, Channel *c, Buffer *m, Buffer *r) /* Channel callbacks fired on read/write from mux slave fd */ static int -mux_master_read_cb(Channel *c) +mux_master_read_cb(struct ssh *ssh, Channel *c) { struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; Buffer in, out; @@ -1141,7 +1169,7 @@ mux_master_read_cb(Channel *c) if (c->mux_ctx == NULL) { state = xcalloc(1, sizeof(*state)); c->mux_ctx = state; - channel_register_cleanup(c->self, + channel_register_cleanup(ssh, c->self, mux_master_control_cleanup_cb, 0); /* Send hello */ @@ -1149,7 +1177,7 @@ mux_master_read_cb(Channel *c) buffer_put_int(&out, MUX_MSG_HELLO); buffer_put_int(&out, SSHMUX_VER); /* no extensions */ - buffer_put_string(&c->output, buffer_ptr(&out), + buffer_put_string(c->output, buffer_ptr(&out), buffer_len(&out)); buffer_free(&out); debug3("%s: channel %d: hello sent", __func__, c->self); @@ -1160,7 +1188,7 @@ mux_master_read_cb(Channel *c) buffer_init(&out); /* Channel code ensures that we receive whole packets */ - if ((ptr = buffer_get_string_ptr_ret(&c->input, &have)) == NULL) { + if ((ptr = buffer_get_string_ptr_ret(c->input, &have)) == NULL) { malf: error("%s: malformed message", __func__); goto out; @@ -1186,7 +1214,8 @@ mux_master_read_cb(Channel *c) for (i = 0; mux_master_handlers[i].handler != NULL; i++) { if (type == mux_master_handlers[i].type) { - ret = mux_master_handlers[i].handler(rid, c, &in, &out); + ret = mux_master_handlers[i].handler(ssh, rid, + c, &in, &out); break; } } @@ -1199,7 +1228,7 @@ mux_master_read_cb(Channel *c) } /* Enqueue reply packet */ if (buffer_len(&out) != 0) { - buffer_put_string(&c->output, buffer_ptr(&out), + buffer_put_string(c->output, buffer_ptr(&out), buffer_len(&out)); } out: @@ -1209,7 +1238,7 @@ mux_master_read_cb(Channel *c) } void -mux_exit_message(Channel *c, int exitval) +mux_exit_message(struct ssh *ssh, Channel *c, int exitval) { Buffer m; Channel *mux_chan; @@ -1217,7 +1246,7 @@ mux_exit_message(Channel *c, int exitval) debug3("%s: channel %d: exit message, exitval %d", __func__, c->self, exitval); - if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL) + if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL) fatal("%s: channel %d missing mux channel %d", __func__, c->self, c->ctl_chan); @@ -1227,19 +1256,19 @@ mux_exit_message(Channel *c, int exitval) buffer_put_int(&m, c->self); buffer_put_int(&m, exitval); - buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m)); + buffer_put_string(mux_chan->output, buffer_ptr(&m), buffer_len(&m)); buffer_free(&m); } void -mux_tty_alloc_failed(Channel *c) +mux_tty_alloc_failed(struct ssh *ssh, Channel *c) { Buffer m; Channel *mux_chan; debug3("%s: channel %d: TTY alloc failed", __func__, c->self); - if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL) + if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL) fatal("%s: channel %d missing mux channel %d", __func__, c->self, c->ctl_chan); @@ -1248,13 +1277,13 @@ mux_tty_alloc_failed(Channel *c) buffer_put_int(&m, MUX_S_TTY_ALLOC_FAIL); buffer_put_int(&m, c->self); - buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m)); + buffer_put_string(mux_chan->output, buffer_ptr(&m), buffer_len(&m)); buffer_free(&m); } /* Prepare a mux master to listen on a Unix domain socket. */ void -muxserver_listen(void) +muxserver_listen(struct ssh *ssh) { mode_t old_umask; char *orig_control_path = options.control_path; @@ -1327,7 +1356,7 @@ muxserver_listen(void) set_nonblock(muxserver_sock); - mux_listener_channel = channel_new("mux listener", + mux_listener_channel = channel_new(ssh, "mux listener", SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, options.control_path, 1); @@ -1338,7 +1367,7 @@ muxserver_listen(void) /* Callback on open confirmation in mux master for a mux client session. */ static void -mux_session_confirm(int id, int success, void *arg) +mux_session_confirm(struct ssh *ssh, int id, int success, void *arg) { struct mux_session_confirm_ctx *cctx = arg; const char *display; @@ -1348,9 +1377,9 @@ mux_session_confirm(int id, int success, void *arg) if (cctx == NULL) fatal("%s: cctx == NULL", __func__); - if ((c = channel_by_id(id)) == NULL) + if ((c = channel_by_id(ssh, id)) == NULL) fatal("%s: no channel for id %d", __func__, id); - if ((cc = channel_by_id(c->ctl_chan)) == NULL) + if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) fatal("%s: channel %d lacks control channel %d", __func__, id, c->ctl_chan); @@ -1369,27 +1398,27 @@ mux_session_confirm(int id, int success, void *arg) char *proto, *data; /* Get reasonable local authentication information. */ - if (client_x11_get_proto(display, options.xauth_location, + if (client_x11_get_proto(ssh, display, options.xauth_location, options.forward_x11_trusted, options.forward_x11_timeout, &proto, &data) == 0) { /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication " "spoofing."); - x11_request_forwarding_with_spoofing(id, display, proto, - data, 1); + x11_request_forwarding_with_spoofing(ssh, id, + display, proto, data, 1); /* XXX exit_on_forward_failure */ - client_expect_confirm(id, "X11 forwarding", + client_expect_confirm(ssh, id, "X11 forwarding", CONFIRM_WARN); } } if (cctx->want_agent_fwd && options.forward_agent) { debug("Requesting authentication agent forwarding."); - channel_request_start(id, "auth-agent-req@openssh.com", 0); + channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0); packet_send(); } - client_session2_setup(id, cctx->want_tty, cctx->want_subsys, + client_session2_setup(ssh, id, cctx->want_tty, cctx->want_subsys, cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env); debug3("%s: sending success reply", __func__); @@ -1401,7 +1430,7 @@ mux_session_confirm(int id, int success, void *arg) done: /* Send reply */ - buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply)); + buffer_put_string(cc->output, buffer_ptr(&reply), buffer_len(&reply)); buffer_free(&reply); if (cc->mux_pause <= 0) @@ -1570,31 +1599,38 @@ mux_client_hello_exchange(int fd) { Buffer m; u_int type, ver; + int ret = -1; buffer_init(&m); buffer_put_int(&m, MUX_MSG_HELLO); buffer_put_int(&m, SSHMUX_VER); /* no extensions */ - if (mux_client_write_packet(fd, &m) != 0) - fatal("%s: write packet: %s", __func__, strerror(errno)); + if (mux_client_write_packet(fd, &m) != 0) { + debug("%s: write packet: %s", __func__, strerror(errno)); + goto out; + } buffer_clear(&m); /* Read their HELLO */ if (mux_client_read_packet(fd, &m) != 0) { - buffer_free(&m); - return -1; + debug("%s: read packet failed", __func__); + goto out; } type = buffer_get_int(&m); - if (type != MUX_MSG_HELLO) - fatal("%s: expected HELLO (%u) received %u", + if (type != MUX_MSG_HELLO) { + error("%s: expected HELLO (%u) received %u", __func__, MUX_MSG_HELLO, type); + goto out; + } ver = buffer_get_int(&m); - if (ver != SSHMUX_VER) - fatal("Unsupported multiplexing protocol version %d " + if (ver != SSHMUX_VER) { + error("Unsupported multiplexing protocol version %d " "(expected %d)", ver, SSHMUX_VER); + goto out; + } debug2("%s: master version %u", __func__, ver); /* No extensions are presently defined */ while (buffer_len(&m) > 0) { @@ -1605,8 +1641,11 @@ mux_client_hello_exchange(int fd) free(name); free(value); } + /* success */ + ret = 0; + out: buffer_free(&m); - return 0; + return ret; } static u_int @@ -1962,7 +2001,7 @@ mux_client_request_session(int fd) leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); if (muxclient_terminate) { - debug2("Exiting on signal %d", muxclient_terminate); + debug2("Exiting on signal: %s", strsignal(muxclient_terminate)); exitval = 255; } else if (!exitval_seen) { debug2("Control master terminated unexpectedly"); diff --git a/myproposal.h b/myproposal.h index 072e36ec7b5e..c255147aa033 100644 --- a/myproposal.h +++ b/myproposal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: myproposal.h,v 1.54 2016/09/28 16:33:07 djm Exp $ */ +/* $OpenBSD: myproposal.h,v 1.55 2017/05/07 23:13:42 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -121,8 +121,7 @@ "aes128-ctr,aes192-ctr,aes256-ctr" \ AESGCM_CIPHER_MODES -#define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT "," \ - "aes128-cbc,aes192-cbc,aes256-cbc" +#define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT #define KEX_SERVER_MAC \ "umac-64-etm@openssh.com," \ diff --git a/nchan.c b/nchan.c index 20f6a2f4990a..24929556dda2 100644 --- a/nchan.c +++ b/nchan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nchan.c,v 1.63 2010/01/26 01:28:35 djm Exp $ */ +/* $OpenBSD: nchan.c,v 1.67 2017/09/12 06:35:32 djm Exp $ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * @@ -33,9 +33,9 @@ #include #include "openbsd-compat/sys-queue.h" -#include "ssh1.h" #include "ssh2.h" -#include "buffer.h" +#include "sshbuf.h" +#include "ssherr.h" #include "packet.h" #include "channels.h" #include "compat.h" @@ -74,18 +74,15 @@ /* * ACTIONS: should never update the channel states */ -static void chan_send_ieof1(Channel *); -static void chan_send_oclose1(Channel *); -static void chan_send_close2(Channel *); -static void chan_send_eof2(Channel *); -static void chan_send_eow2(Channel *); +static void chan_send_eof2(struct ssh *, Channel *); +static void chan_send_eow2(struct ssh *, Channel *); /* helper */ -static void chan_shutdown_write(Channel *); -static void chan_shutdown_read(Channel *); +static void chan_shutdown_write(struct ssh *, Channel *); +static void chan_shutdown_read(struct ssh *, Channel *); -static char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; -static char *istates[] = { "open", "drain", "wait_oclose", "closed" }; +static const char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; +static const char *istates[] = { "open", "drain", "wait_oclose", "closed" }; static void chan_set_istate(Channel *c, u_int next) @@ -96,6 +93,7 @@ chan_set_istate(Channel *c, u_int next) istates[next]); c->istate = next; } + static void chan_set_ostate(Channel *c, u_int next) { @@ -106,41 +104,13 @@ chan_set_ostate(Channel *c, u_int next) c->ostate = next; } -/* - * SSH1 specific implementation of event functions - */ - -static void -chan_rcvd_oclose1(Channel *c) -{ - debug2("channel %d: rcvd oclose", c->self); - switch (c->istate) { - case CHAN_INPUT_WAIT_OCLOSE: - chan_set_istate(c, CHAN_INPUT_CLOSED); - break; - case CHAN_INPUT_OPEN: - chan_shutdown_read(c); - chan_send_ieof1(c); - chan_set_istate(c, CHAN_INPUT_CLOSED); - break; - case CHAN_INPUT_WAIT_DRAIN: - /* both local read_failed and remote write_failed */ - chan_send_ieof1(c); - chan_set_istate(c, CHAN_INPUT_CLOSED); - break; - default: - error("channel %d: protocol error: rcvd_oclose for istate %d", - c->self, c->istate); - return; - } -} void -chan_read_failed(Channel *c) +chan_read_failed(struct ssh *ssh, Channel *c) { debug2("channel %d: read failed", c->self); switch (c->istate) { case CHAN_INPUT_OPEN: - chan_shutdown_read(c); + chan_shutdown_read(ssh, c); chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); break; default: @@ -149,25 +119,21 @@ chan_read_failed(Channel *c) break; } } + void -chan_ibuf_empty(Channel *c) +chan_ibuf_empty(struct ssh *ssh, Channel *c) { debug2("channel %d: ibuf empty", c->self); - if (buffer_len(&c->input)) { + if (sshbuf_len(c->input)) { error("channel %d: chan_ibuf_empty for non empty buffer", c->self); return; } switch (c->istate) { case CHAN_INPUT_WAIT_DRAIN: - if (compat20) { - if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL))) - chan_send_eof2(c); - chan_set_istate(c, CHAN_INPUT_CLOSED); - } else { - chan_send_ieof1(c); - chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE); - } + if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL))) + chan_send_eof2(ssh, c); + chan_set_istate(c, CHAN_INPUT_CLOSED); break; default: error("channel %d: chan_ibuf_empty for istate %d", @@ -175,58 +141,19 @@ chan_ibuf_empty(Channel *c) break; } } -static void -chan_rcvd_ieof1(Channel *c) -{ - debug2("channel %d: rcvd ieof", c->self); - switch (c->ostate) { - case CHAN_OUTPUT_OPEN: - chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); - break; - case CHAN_OUTPUT_WAIT_IEOF: - chan_set_ostate(c, CHAN_OUTPUT_CLOSED); - break; - default: - error("channel %d: protocol error: rcvd_ieof for ostate %d", - c->self, c->ostate); - break; - } -} -static void -chan_write_failed1(Channel *c) -{ - debug2("channel %d: write failed", c->self); - switch (c->ostate) { - case CHAN_OUTPUT_OPEN: - chan_shutdown_write(c); - chan_send_oclose1(c); - chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF); - break; - case CHAN_OUTPUT_WAIT_DRAIN: - chan_shutdown_write(c); - chan_send_oclose1(c); - chan_set_ostate(c, CHAN_OUTPUT_CLOSED); - break; - default: - error("channel %d: chan_write_failed for ostate %d", - c->self, c->ostate); - break; - } -} + void -chan_obuf_empty(Channel *c) +chan_obuf_empty(struct ssh *ssh, Channel *c) { debug2("channel %d: obuf empty", c->self); - if (buffer_len(&c->output)) { + if (sshbuf_len(c->output)) { error("channel %d: chan_obuf_empty for non empty buffer", c->self); return; } switch (c->ostate) { case CHAN_OUTPUT_WAIT_DRAIN: - chan_shutdown_write(c); - if (!compat20) - chan_send_oclose1(c); + chan_shutdown_write(ssh, c); chan_set_ostate(c, CHAN_OUTPUT_CLOSED); break; default: @@ -235,47 +162,107 @@ chan_obuf_empty(Channel *c) break; } } -static void -chan_send_ieof1(Channel *c) + +void +chan_rcvd_eow(struct ssh *ssh, Channel *c) { - debug2("channel %d: send ieof", c->self); + debug2("channel %d: rcvd eow", c->self); switch (c->istate) { case CHAN_INPUT_OPEN: - case CHAN_INPUT_WAIT_DRAIN: - packet_start(SSH_MSG_CHANNEL_INPUT_EOF); - packet_put_int(c->remote_id); - packet_send(); - break; - default: - error("channel %d: cannot send ieof for istate %d", - c->self, c->istate); - break; - } -} -static void -chan_send_oclose1(Channel *c) -{ - debug2("channel %d: send oclose", c->self); - switch (c->ostate) { - case CHAN_OUTPUT_OPEN: - case CHAN_OUTPUT_WAIT_DRAIN: - buffer_clear(&c->output); - packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE); - packet_put_int(c->remote_id); - packet_send(); - break; - default: - error("channel %d: cannot send oclose for ostate %d", - c->self, c->ostate); + chan_shutdown_read(ssh, c); + chan_set_istate(c, CHAN_INPUT_CLOSED); break; } } -/* - * the same for SSH2 - */ static void -chan_rcvd_close2(Channel *c) +chan_send_eof2(struct ssh *ssh, Channel *c) +{ + int r; + + debug2("channel %d: send eof", c->self); + switch (c->istate) { + case CHAN_INPUT_WAIT_DRAIN: + if (!c->have_remote_id) + fatal("%s: channel %d: no remote_id", + __func__, c->self); + if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EOF)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); + c->flags |= CHAN_EOF_SENT; + break; + default: + error("channel %d: cannot send eof for istate %d", + c->self, c->istate); + break; + } +} + +static void +chan_send_close2(struct ssh *ssh, Channel *c) +{ + int r; + + debug2("channel %d: send close", c->self); + if (c->ostate != CHAN_OUTPUT_CLOSED || + c->istate != CHAN_INPUT_CLOSED) { + error("channel %d: cannot send close for istate/ostate %d/%d", + c->self, c->istate, c->ostate); + } else if (c->flags & CHAN_CLOSE_SENT) { + error("channel %d: already sent close", c->self); + } else { + if (!c->have_remote_id) + fatal("%s: channel %d: no remote_id", + __func__, c->self); + if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_CLOSE)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); + c->flags |= CHAN_CLOSE_SENT; + } +} + +static void +chan_send_eow2(struct ssh *ssh, Channel *c) +{ + int r; + + debug2("channel %d: send eow", c->self); + if (c->ostate == CHAN_OUTPUT_CLOSED) { + error("channel %d: must not sent eow on closed output", + c->self); + return; + } + if (!(datafellows & SSH_NEW_OPENSSH)) + return; + if (!c->have_remote_id) + fatal("%s: channel %d: no remote_id", __func__, c->self); + if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 || + (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || + (r = sshpkt_put_cstring(ssh, "eow@openssh.com")) != 0 || + (r = sshpkt_put_u8(ssh, 0)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); +} + +/* shared */ + +void +chan_rcvd_ieof(struct ssh *ssh, Channel *c) +{ + debug2("channel %d: rcvd eof", c->self); + c->flags |= CHAN_EOF_RCVD; + if (c->ostate == CHAN_OUTPUT_OPEN) + chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); + if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && + sshbuf_len(c->output) == 0 && + !CHANNEL_EFD_OUTPUT_ACTIVE(c)) + chan_obuf_empty(ssh, c); +} + +void +chan_rcvd_oclose(struct ssh *ssh, Channel *c) { debug2("channel %d: rcvd close", c->self); if (!(c->flags & CHAN_LOCAL)) { @@ -301,46 +288,27 @@ chan_rcvd_close2(Channel *c) } switch (c->istate) { case CHAN_INPUT_OPEN: - chan_shutdown_read(c); + chan_shutdown_read(ssh, c); chan_set_istate(c, CHAN_INPUT_CLOSED); break; case CHAN_INPUT_WAIT_DRAIN: if (!(c->flags & CHAN_LOCAL)) - chan_send_eof2(c); + chan_send_eof2(ssh, c); chan_set_istate(c, CHAN_INPUT_CLOSED); break; } } void -chan_rcvd_eow(Channel *c) -{ - debug2("channel %d: rcvd eow", c->self); - switch (c->istate) { - case CHAN_INPUT_OPEN: - chan_shutdown_read(c); - chan_set_istate(c, CHAN_INPUT_CLOSED); - break; - } -} -static void -chan_rcvd_eof2(Channel *c) -{ - debug2("channel %d: rcvd eof", c->self); - c->flags |= CHAN_EOF_RCVD; - if (c->ostate == CHAN_OUTPUT_OPEN) - chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); -} -static void -chan_write_failed2(Channel *c) +chan_write_failed(struct ssh *ssh, Channel *c) { debug2("channel %d: write failed", c->self); switch (c->ostate) { case CHAN_OUTPUT_OPEN: case CHAN_OUTPUT_WAIT_DRAIN: - chan_shutdown_write(c); + chan_shutdown_write(ssh, c); if (strcmp(c->ctype, "session") == 0) - chan_send_eow2(c); + chan_send_eow2(ssh, c); chan_set_ostate(c, CHAN_OUTPUT_CLOSED); break; default: @@ -349,97 +317,15 @@ chan_write_failed2(Channel *c) break; } } -static void -chan_send_eof2(Channel *c) -{ - debug2("channel %d: send eof", c->self); - switch (c->istate) { - case CHAN_INPUT_WAIT_DRAIN: - packet_start(SSH2_MSG_CHANNEL_EOF); - packet_put_int(c->remote_id); - packet_send(); - c->flags |= CHAN_EOF_SENT; - break; - default: - error("channel %d: cannot send eof for istate %d", - c->self, c->istate); - break; - } -} -static void -chan_send_close2(Channel *c) -{ - debug2("channel %d: send close", c->self); - if (c->ostate != CHAN_OUTPUT_CLOSED || - c->istate != CHAN_INPUT_CLOSED) { - error("channel %d: cannot send close for istate/ostate %d/%d", - c->self, c->istate, c->ostate); - } else if (c->flags & CHAN_CLOSE_SENT) { - error("channel %d: already sent close", c->self); - } else { - packet_start(SSH2_MSG_CHANNEL_CLOSE); - packet_put_int(c->remote_id); - packet_send(); - c->flags |= CHAN_CLOSE_SENT; - } -} -static void -chan_send_eow2(Channel *c) -{ - debug2("channel %d: send eow", c->self); - if (c->ostate == CHAN_OUTPUT_CLOSED) { - error("channel %d: must not sent eow on closed output", - c->self); - return; - } - if (!(datafellows & SSH_NEW_OPENSSH)) - return; - packet_start(SSH2_MSG_CHANNEL_REQUEST); - packet_put_int(c->remote_id); - packet_put_cstring("eow@openssh.com"); - packet_put_char(0); - packet_send(); -} - -/* shared */ void -chan_rcvd_ieof(Channel *c) -{ - if (compat20) - chan_rcvd_eof2(c); - else - chan_rcvd_ieof1(c); - if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && - buffer_len(&c->output) == 0 && - !CHANNEL_EFD_OUTPUT_ACTIVE(c)) - chan_obuf_empty(c); -} -void -chan_rcvd_oclose(Channel *c) -{ - if (compat20) - chan_rcvd_close2(c); - else - chan_rcvd_oclose1(c); -} -void -chan_write_failed(Channel *c) -{ - if (compat20) - chan_write_failed2(c); - else - chan_write_failed1(c); -} - -void -chan_mark_dead(Channel *c) +chan_mark_dead(struct ssh *ssh, Channel *c) { c->type = SSH_CHANNEL_ZOMBIE; } int -chan_is_dead(Channel *c, int do_send) +chan_is_dead(struct ssh *ssh, Channel *c, int do_send) { if (c->type == SSH_CHANNEL_ZOMBIE) { debug2("channel %d: zombie", c->self); @@ -447,16 +333,12 @@ chan_is_dead(Channel *c, int do_send) } if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED) return 0; - if (!compat20) { - debug2("channel %d: is dead", c->self); - return 1; - } if ((datafellows & SSH_BUG_EXTEOF) && c->extended_usage == CHAN_EXTENDED_WRITE && c->efd != -1 && - buffer_len(&c->extended) > 0) { - debug2("channel %d: active efd: %d len %d", - c->self, c->efd, buffer_len(&c->extended)); + sshbuf_len(c->extended) > 0) { + debug2("channel %d: active efd: %d len %zu", + c->self, c->efd, sshbuf_len(c->extended)); return 0; } if (c->flags & CHAN_LOCAL) { @@ -465,7 +347,7 @@ chan_is_dead(Channel *c, int do_send) } if (!(c->flags & CHAN_CLOSE_SENT)) { if (do_send) { - chan_send_close2(c); + chan_send_close2(ssh, c); } else { /* channel would be dead if we sent a close */ if (c->flags & CHAN_CLOSE_RCVD) { @@ -485,10 +367,10 @@ chan_is_dead(Channel *c, int do_send) /* helper */ static void -chan_shutdown_write(Channel *c) +chan_shutdown_write(struct ssh *ssh, Channel *c) { - buffer_clear(&c->output); - if (compat20 && c->type == SSH_CHANNEL_LARVAL) + sshbuf_reset(c->output); + if (c->type == SSH_CHANNEL_LARVAL) return; /* shutdown failure is allowed if write failed already */ debug2("channel %d: close_write", c->self); @@ -498,16 +380,17 @@ chan_shutdown_write(Channel *c) "shutdown() failed for fd %d: %.100s", c->self, c->sock, strerror(errno)); } else { - if (channel_close_fd(&c->wfd) < 0) + if (channel_close_fd(ssh, &c->wfd) < 0) logit("channel %d: chan_shutdown_write: " "close() failed for fd %d: %.100s", c->self, c->wfd, strerror(errno)); } } + static void -chan_shutdown_read(Channel *c) +chan_shutdown_read(struct ssh *ssh, Channel *c) { - if (compat20 && c->type == SSH_CHANNEL_LARVAL) + if (c->type == SSH_CHANNEL_LARVAL) return; debug2("channel %d: close_read", c->self); if (c->sock != -1) { @@ -523,7 +406,7 @@ chan_shutdown_read(Channel *c) c->self, c->sock, c->istate, c->ostate, strerror(errno)); } else { - if (channel_close_fd(&c->rfd) < 0) + if (channel_close_fd(ssh, &c->rfd) < 0) logit("channel %d: chan_shutdown_read: " "close() failed for fd %d: %.100s", c->self, c->rfd, strerror(errno)); diff --git a/opacket.c b/opacket.c index 5970dd3771cc..ad244b452634 100644 --- a/opacket.c +++ b/opacket.c @@ -74,16 +74,6 @@ ssh_packet_put_raw(struct ssh *ssh, const void *buf, u_int len) fatal("%s: %s", __func__, ssh_err(r)); } -#ifdef WITH_SSH1 -void -ssh_packet_put_bignum(struct ssh *ssh, BIGNUM * value) -{ - int r; - - if ((r = sshpkt_put_bignum1(ssh, value)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); -} -#endif #ifdef WITH_OPENSSL void @@ -150,16 +140,6 @@ ssh_packet_get_int64(struct ssh *ssh) return val; } -#ifdef WITH_SSH1 -void -ssh_packet_get_bignum(struct ssh *ssh, BIGNUM * value) -{ - int r; - - if ((r = sshpkt_get_bignum1(ssh, value)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); -} -#endif #ifdef WITH_OPENSSL void diff --git a/opacket.h b/opacket.h index c487f4f40d68..c49d0c04a790 100644 --- a/opacket.h +++ b/opacket.h @@ -6,7 +6,6 @@ void ssh_packet_start(struct ssh *, u_char); void ssh_packet_put_char(struct ssh *, int ch); void ssh_packet_put_int(struct ssh *, u_int value); void ssh_packet_put_int64(struct ssh *, u_int64_t value); -void ssh_packet_put_bignum(struct ssh *, BIGNUM * value); void ssh_packet_put_bignum2(struct ssh *, BIGNUM * value); void ssh_packet_put_ecpoint(struct ssh *, const EC_GROUP *, const EC_POINT *); void ssh_packet_put_string(struct ssh *, const void *buf, u_int len); @@ -17,7 +16,6 @@ void ssh_packet_send(struct ssh *); u_int ssh_packet_get_char(struct ssh *); u_int ssh_packet_get_int(struct ssh *); u_int64_t ssh_packet_get_int64(struct ssh *); -void ssh_packet_get_bignum(struct ssh *, BIGNUM * value); void ssh_packet_get_bignum2(struct ssh *, BIGNUM * value); void ssh_packet_get_ecpoint(struct ssh *, const EC_GROUP *, EC_POINT *); void *ssh_packet_get_string(struct ssh *, u_int *length_ptr); @@ -62,8 +60,6 @@ void packet_read_expect(int expected_type); ssh_packet_get_protocol_flags(active_state) #define packet_start_compression(level) \ ssh_packet_start_compression(active_state, (level)) -#define packet_set_encryption_key(key, keylen, number) \ - ssh_packet_set_encryption_key(active_state, (key), (keylen), (number)) #define packet_start(type) \ ssh_packet_start(active_state, (type)) #define packet_put_char(value) \ @@ -78,8 +74,6 @@ void packet_read_expect(int expected_type); ssh_packet_put_cstring(active_state, (str)) #define packet_put_raw(buf, len) \ ssh_packet_put_raw(active_state, (buf), (len)) -#define packet_put_bignum(value) \ - ssh_packet_put_bignum(active_state, (value)) #define packet_put_bignum2(value) \ ssh_packet_put_bignum2(active_state, (value)) #define packet_send() \ @@ -88,8 +82,6 @@ void packet_read_expect(int expected_type); ssh_packet_read(active_state) #define packet_get_int64() \ ssh_packet_get_int64(active_state) -#define packet_get_bignum(value) \ - ssh_packet_get_bignum(active_state, (value)) #define packet_get_bignum2(value) \ ssh_packet_get_bignum2(active_state, (value)) #define packet_remaining() \ @@ -157,5 +149,7 @@ void packet_disconnect(const char *, ...) ssh_packet_set_mux(active_state) #define packet_get_mux() \ ssh_packet_get_mux(active_state) +#define packet_clear_keys() \ + ssh_packet_clear_keys(active_state) #endif /* _OPACKET_H */ diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in index d51eacf6562a..ac8ae4305d0b 100644 --- a/openbsd-compat/Makefile.in +++ b/openbsd-compat/Makefile.in @@ -16,9 +16,9 @@ RANLIB=@RANLIB@ INSTALL=@INSTALL@ LDFLAGS=-L. @LDFLAGS@ -OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o reallocarray.o realpath.o rresvport.o setenv.o setproctitle.o sha1.o sha2.o rmd160.o md5.o sigact.o strcasestr.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o +OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o reallocarray.o realpath.o recallocarray.o rresvport.o setenv.o setproctitle.o sha1.o sha2.o rmd160.o md5.o sigact.o strcasestr.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o freezero.o -COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-err.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xcrypt.o kludge-fd_set.o +COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-err.o bsd-getpagesize.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-malloc.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xcrypt.o kludge-fd_set.o PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o diff --git a/openbsd-compat/bsd-err.c b/openbsd-compat/bsd-err.c index ab10646f023a..e4ed22b86a25 100644 --- a/openbsd-compat/bsd-err.c +++ b/openbsd-compat/bsd-err.c @@ -27,6 +27,12 @@ #include "includes.h" +#include +#include +#include +#include +#include + #ifndef HAVE_ERR void err(int r, const char *fmt, ...) diff --git a/openbsd-compat/bsd-getpagesize.c b/openbsd-compat/bsd-getpagesize.c new file mode 100644 index 000000000000..9daddfbd3865 --- /dev/null +++ b/openbsd-compat/bsd-getpagesize.c @@ -0,0 +1,23 @@ +/* Placed in the public domain */ + +#ifndef HAVE_GETPAGESIZE + +#include +#include + +int +getpagesize(void) +{ +#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) + long r = sysconf(_SC_PAGESIZE); + if (r > 0 && r < INT_MAX) + return (int)r; +#endif + /* + * This is at the lower end of common values and appropriate for + * our current use of getpagesize() in recallocarray(). + */ + return 4096; +} + +#endif /* HAVE_GETPAGESIZE */ diff --git a/openbsd-compat/bsd-malloc.c b/openbsd-compat/bsd-malloc.c new file mode 100644 index 000000000000..6402ab588b09 --- /dev/null +++ b/openbsd-compat/bsd-malloc.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017 Darren Tucker (dtucker at zip com au). + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" +#undef malloc +#undef calloc +#undef realloc + +#include +#include + +#if defined(HAVE_MALLOC) && HAVE_MALLOC == 0 +void * +rpl_malloc(size_t size) +{ + if (size == 0) + size = 1; + return malloc(size); +} +#endif + +#if defined(HAVE_CALLOC) && HAVE_CALLOC == 0 +void * +rpl_calloc(size_t nmemb, size_t size) +{ + if (nmemb == 0) + nmemb = 1; + if (size == 0) + size = 1; + return calloc(nmemb, size); +} +#endif + +#if defined (HAVE_REALLOC) && HAVE_REALLOC == 0 +void * +rpl_realloc(void *ptr, size_t size) +{ + if (size == 0) + size = 1; + return realloc(ptr, size); +} +#endif diff --git a/openbsd-compat/bsd-misc.c b/openbsd-compat/bsd-misc.c index cfd73260ae18..29f6ad38c5a1 100644 --- a/openbsd-compat/bsd-misc.c +++ b/openbsd-compat/bsd-misc.c @@ -104,6 +104,16 @@ const char *strerror(int e) } #endif +#if !defined(HAVE_STRSIGNAL) +char *strsignal(int sig) +{ + static char buf[16]; + + (void)snprintf(buf, sizeof(buf), "%d", sig); + return buf; +} +#endif + #ifndef HAVE_UTIMES int utimes(char *filename, struct timeval *tvp) { diff --git a/openbsd-compat/bsd-misc.h b/openbsd-compat/bsd-misc.h index 70a538f04e2d..0b1a3504f2cc 100644 --- a/openbsd-compat/bsd-misc.h +++ b/openbsd-compat/bsd-misc.h @@ -49,6 +49,10 @@ int setegid(uid_t); const char *strerror(int); #endif +#if !defined(HAVE_STRSIGNAL) +char *strsignal(int); +#endif + #if !defined(HAVE_SETLINEBUF) #define setlinebuf(a) (setvbuf((a), NULL, _IOLBF, 0)) #endif diff --git a/openbsd-compat/explicit_bzero.c b/openbsd-compat/explicit_bzero.c index 5078134d137a..53a003472721 100644 --- a/openbsd-compat/explicit_bzero.c +++ b/openbsd-compat/explicit_bzero.c @@ -20,6 +20,8 @@ void explicit_bzero(void *p, size_t n) { + if (n == 0) + return; (void)memset_s(p, n, 0, n); } @@ -34,6 +36,8 @@ static void (* volatile ssh_bzero)(void *, size_t) = bzero; void explicit_bzero(void *p, size_t n) { + if (n == 0) + return; /* * clang -fsanitize=memory needs to intercept memset-like functions * to correctly detect memory initialisation. Make sure one is called diff --git a/openbsd-compat/fmt_scaled.c b/openbsd-compat/fmt_scaled.c index e5533b2de90c..7c5193e26d95 100644 --- a/openbsd-compat/fmt_scaled.c +++ b/openbsd-compat/fmt_scaled.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fmt_scaled.c,v 1.13 2017/03/11 23:37:23 djm Exp $ */ +/* $OpenBSD: fmt_scaled.c,v 1.16 2017/03/16 02:40:46 dtucker Exp $ */ /* * Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved. @@ -125,22 +125,30 @@ scan_scaled(char *scaled, long long *result) /* ignore extra fractional digits */ continue; fract_digits++; /* for later scaling */ - if (fpart >= LLONG_MAX / 10) { + if (fpart > LLONG_MAX / 10) { errno = ERANGE; return -1; } fpart *= 10; + if (i > LLONG_MAX - fpart) { + errno = ERANGE; + return -1; + } fpart += i; } else { /* normal digit */ if (++ndigits >= MAX_DIGITS) { errno = ERANGE; return -1; } - if (whole >= LLONG_MAX / 10) { + if (whole > LLONG_MAX / 10) { errno = ERANGE; return -1; } whole *= 10; + if (i > LLONG_MAX - whole) { + errno = ERANGE; + return -1; + } whole += i; } } @@ -170,7 +178,9 @@ scan_scaled(char *scaled, long long *result) } scale_fact = scale_factors[i]; - if (whole >= LLONG_MAX / scale_fact) { + /* check for overflow and underflow after scaling */ + if (whole > LLONG_MAX / scale_fact || + whole < LLONG_MIN / scale_fact) { errno = ERANGE; return -1; } diff --git a/openbsd-compat/freezero.c b/openbsd-compat/freezero.c new file mode 100644 index 000000000000..3af8f4a733e9 --- /dev/null +++ b/openbsd-compat/freezero.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#ifndef HAVE_FREEZERO + +void +freezero(void *ptr, size_t sz) +{ + explicit_bzero(ptr, sz); + free(ptr); +} + +#endif /* HAVE_FREEZERO */ + diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h index cff547745b88..cac799e8446f 100644 --- a/openbsd-compat/openbsd-compat.h +++ b/openbsd-compat/openbsd-compat.h @@ -60,6 +60,10 @@ int bindresvport_sa(int sd, struct sockaddr *sa); void closefrom(int); #endif +#ifndef HAVE_GETPAGESIZE +int getpagesize(void); +#endif + #ifndef HAVE_GETCWD char *getcwd(char *pt, size_t size); #endif @@ -68,6 +72,10 @@ char *getcwd(char *pt, size_t size); void *reallocarray(void *, size_t, size_t); #endif +#ifndef HAVE_RECALLOCARRAY +void *recallocarray(void *, size_t, size_t, size_t); +#endif + #if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) /* * glibc's FORTIFY_SOURCE can redefine this and prevent us picking up the @@ -296,6 +304,10 @@ int bcrypt_pbkdf(const char *, size_t, const u_int8_t *, size_t, void explicit_bzero(void *p, size_t n); #endif +#ifndef HAVE_FREEZERO +void freezero(void *, size_t); +#endif + char *xcrypt(const char *password, const char *salt); char *shadow_pw(struct passwd *pw); diff --git a/openbsd-compat/port-tun.c b/openbsd-compat/port-tun.c index a444adf1d593..7579c6084a1f 100644 --- a/openbsd-compat/port-tun.c +++ b/openbsd-compat/port-tun.c @@ -199,84 +199,81 @@ sys_tun_open(int tun, int mode) */ #if defined(SSH_TUN_FILTER) +/* + * The tunnel forwarding protocol prepends the address family of forwarded + * IP packets using OpenBSD's numbers. + */ #define OPENBSD_AF_INET 2 #define OPENBSD_AF_INET6 24 int -sys_tun_infilter(struct Channel *c, char *buf, int len) +sys_tun_infilter(struct ssh *ssh, struct Channel *c, char *buf, int _len) { + int r; + size_t len; + char *ptr = buf; #if defined(SSH_TUN_PREPEND_AF) char rbuf[CHAN_RBUF]; - struct ip *iph; + struct ip iph; #endif - u_int32_t *af; - char *ptr = buf; - int r; +#if defined(SSH_TUN_PREPEND_AF) || defined(SSH_TUN_COMPAT_AF) + u_int32_t af; +#endif + + /* XXX update channel input filter API to use unsigned length */ + if (_len < 0) + return -1; + len = _len; #if defined(SSH_TUN_PREPEND_AF) - if (len <= 0 || len > (int)(sizeof(rbuf) - sizeof(*af))) - return (-1); - ptr = (char *)&rbuf[0]; - bcopy(buf, ptr + sizeof(u_int32_t), len); - len += sizeof(u_int32_t); - af = (u_int32_t *)ptr; - - iph = (struct ip *)(ptr + sizeof(u_int32_t)); - switch (iph->ip_v) { - case 6: - *af = AF_INET6; - break; - case 4: - default: - *af = AF_INET; - break; - } + if (len <= sizeof(iph) || len > sizeof(rbuf) - 4) + return -1; + /* Determine address family from packet IP header. */ + memcpy(&iph, buf, sizeof(iph)); + af = iph.ip_v == 6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET; + /* Prepend address family to packet using OpenBSD constants */ + memcpy(rbuf + 4, buf, len); + len += 4; + POKE_U32(rbuf, af); + ptr = rbuf; +#elif defined(SSH_TUN_COMPAT_AF) + /* Convert existing address family header to OpenBSD value */ + if (len <= 4) + return -1; + af = PEEK_U32(buf); + /* Put it back */ + POKE_U32(buf, af == AF_INET6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET); #endif -#if defined(SSH_TUN_COMPAT_AF) - if (len < (int)sizeof(u_int32_t)) - return (-1); - - af = (u_int32_t *)ptr; - if (*af == htonl(AF_INET6)) - *af = htonl(OPENBSD_AF_INET6); - else - *af = htonl(OPENBSD_AF_INET); -#endif - - if ((r = sshbuf_put_string(&c->input, ptr, len)) != 0) + if ((r = sshbuf_put_string(c->input, ptr, len)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); return (0); } u_char * -sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen) +sys_tun_outfilter(struct ssh *ssh, struct Channel *c, + u_char **data, size_t *dlen) { u_char *buf; - u_int32_t *af; + u_int32_t af; int r; - size_t xxx_dlen; /* XXX new API is incompatible with this signature. */ - if ((r = sshbuf_get_string(&c->output, data, &xxx_dlen)) != 0) + if ((r = sshbuf_get_string(c->output, data, dlen)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); - if (dlen != NULL) - *dlen = xxx_dlen; - if (*dlen < sizeof(*af)) + if (*dlen < sizeof(af)) return (NULL); buf = *data; #if defined(SSH_TUN_PREPEND_AF) - *dlen -= sizeof(u_int32_t); - buf = *data + sizeof(u_int32_t); + /* skip address family */ + *dlen -= sizeof(af); + buf = *data + sizeof(af); #elif defined(SSH_TUN_COMPAT_AF) - af = ntohl(*(u_int32_t *)buf); - if (*af == OPENBSD_AF_INET6) - *af = htonl(AF_INET6); - else - *af = htonl(AF_INET); + /* translate address family */ + af = (PEEK_U32(buf) == OPENBSD_AF_INET6) ? AF_INET6 : AF_INET; + POKE_U32(buf, af); #endif - return (buf); } #endif /* SSH_TUN_FILTER */ diff --git a/openbsd-compat/port-tun.h b/openbsd-compat/port-tun.h index c53df01fceb6..103514370fd3 100644 --- a/openbsd-compat/port-tun.h +++ b/openbsd-compat/port-tun.h @@ -18,6 +18,7 @@ #define _PORT_TUN_H struct Channel; +struct ssh; #if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD) # define CUSTOM_SYS_TUN_OPEN @@ -26,8 +27,8 @@ int sys_tun_open(int, int); #if defined(SSH_TUN_COMPAT_AF) || defined(SSH_TUN_PREPEND_AF) # define SSH_TUN_FILTER -int sys_tun_infilter(struct Channel *, char *, int); -u_char *sys_tun_outfilter(struct Channel *, u_char **, u_int *); +int sys_tun_infilter(struct ssh *, struct Channel *, char *, int); +u_char *sys_tun_outfilter(struct ssh *, struct Channel *, u_char **, size_t *); #endif #endif diff --git a/openbsd-compat/recallocarray.c b/openbsd-compat/recallocarray.c new file mode 100644 index 000000000000..3e1156ce2d95 --- /dev/null +++ b/openbsd-compat/recallocarray.c @@ -0,0 +1,90 @@ +/* $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $ */ +/* + * Copyright (c) 2008, 2017 Otto Moerbeek + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* OPENBSD ORIGINAL: lib/libc/stdlib/recallocarray.c */ + +#include "includes.h" +#ifndef HAVE_RECALLOCARRAY + +#include +#include +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void * +recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size) +{ + size_t oldsize, newsize; + void *newptr; + + if (ptr == NULL) + return calloc(newnmemb, size); + + if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + newnmemb > 0 && SIZE_MAX / newnmemb < size) { + errno = ENOMEM; + return NULL; + } + newsize = newnmemb * size; + + if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + oldnmemb > 0 && SIZE_MAX / oldnmemb < size) { + errno = EINVAL; + return NULL; + } + oldsize = oldnmemb * size; + + /* + * Don't bother too much if we're shrinking just a bit, + * we do not shrink for series of small steps, oh well. + */ + if (newsize <= oldsize) { + size_t d = oldsize - newsize; + + if (d < oldsize / 2 && d < (size_t)getpagesize()) { + memset((char *)ptr + newsize, 0, d); + return ptr; + } + } + + newptr = malloc(newsize); + if (newptr == NULL) + return NULL; + + if (newsize > oldsize) { + memcpy(newptr, ptr, oldsize); + memset((char *)newptr + oldsize, 0, newsize - oldsize); + } else + memcpy(newptr, ptr, newsize); + + explicit_bzero(ptr, oldsize); + free(ptr); + + return newptr; +} +/* DEF_WEAK(recallocarray); */ + +#endif /* HAVE_RECALLOCARRAY */ diff --git a/packet.c b/packet.c index 2f3a2ec7075c..f114ea52c648 100644 --- a/packet.c +++ b/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.247 2017/03/11 13:07:35 markus Exp $ */ +/* $OpenBSD: packet.c,v 1.264 2017/09/12 06:32:07 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -68,9 +68,7 @@ #include "xmalloc.h" #include "crc32.h" -#include "deattack.h" #include "compat.h" -#include "ssh1.h" #include "ssh2.h" #include "cipher.h" #include "sshkey.h" @@ -186,10 +184,6 @@ struct session_state { u_int32_t rekey_interval; /* how often in seconds */ time_t rekey_time; /* time of last rekeying */ - /* Session key for protocol v1 */ - u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; - u_int ssh1_keylen; - /* roundup current message to extra_pad bytes */ u_char extra_pad; @@ -216,9 +210,6 @@ struct session_state { /* One-off warning about weak ciphers */ int cipher_warning_done; - /* SSH1 CRC compensation attack detector */ - struct deattack_ctx deattack; - /* Hook for fuzzing inbound packets */ ssh_packet_hook_fn *hook_in; void *hook_in_ctx; @@ -278,13 +269,12 @@ ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx) int ssh_packet_is_rekeying(struct ssh *ssh) { - return compat20 && - (ssh->state->rekeying || (ssh->kex != NULL && ssh->kex->done == 0)); + return ssh->state->rekeying || + (ssh->kex != NULL && ssh->kex->done == 0); } /* - * Sets the descriptors used for communication. Disables encryption until - * packet_set_encryption_key is called. + * Sets the descriptors used for communication. */ struct ssh * ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out) @@ -315,7 +305,6 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out) return NULL; } state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL; - deattack_init(&state->deattack); /* * Cache the IP address of the remote connection for use in error * messages that might be generated after the connection has closed. @@ -570,8 +559,8 @@ ssh_local_port(struct ssh *ssh) /* Closes the connection and clears and frees internal data structures. */ -void -ssh_packet_close(struct ssh *ssh) +static void +ssh_packet_close_internal(struct ssh *ssh, int do_close) { struct session_state *state = ssh->state; u_int mode; @@ -579,20 +568,25 @@ ssh_packet_close(struct ssh *ssh) if (!state->initialized) return; state->initialized = 0; - if (state->connection_in == state->connection_out) { - shutdown(state->connection_out, SHUT_RDWR); - close(state->connection_out); - } else { - close(state->connection_in); - close(state->connection_out); + if (do_close) { + if (state->connection_in == state->connection_out) { + close(state->connection_out); + } else { + close(state->connection_in); + close(state->connection_out); + } } sshbuf_free(state->input); sshbuf_free(state->output); sshbuf_free(state->outgoing_packet); sshbuf_free(state->incoming_packet); - for (mode = 0; mode < MODE_MAX; mode++) - kex_free_newkeys(state->newkeys[mode]); - if (state->compression_buffer) { + for (mode = 0; mode < MODE_MAX; mode++) { + kex_free_newkeys(state->newkeys[mode]); /* current keys */ + state->newkeys[mode] = NULL; + ssh_clear_newkeys(ssh, mode); /* next keys */ + } + /* comression state is in shared mem, so we can only release it once */ + if (do_close && state->compression_buffer) { sshbuf_free(state->compression_buffer); if (state->compression_out_started) { z_streamp stream = &state->compression_out_stream; @@ -606,7 +600,7 @@ ssh_packet_close(struct ssh *ssh) deflateEnd(stream); } if (state->compression_in_started) { - z_streamp stream = &state->compression_out_stream; + z_streamp stream = &state->compression_in_stream; debug("compress incoming: " "raw data %llu, compressed %llu, factor %.2f", (unsigned long long)stream->total_out, @@ -620,10 +614,24 @@ ssh_packet_close(struct ssh *ssh) cipher_free(state->send_context); cipher_free(state->receive_context); state->send_context = state->receive_context = NULL; - free(ssh->remote_ipaddr); - ssh->remote_ipaddr = NULL; - free(ssh->state); - ssh->state = NULL; + if (do_close) { + free(ssh->remote_ipaddr); + ssh->remote_ipaddr = NULL; + free(ssh->state); + ssh->state = NULL; + } +} + +void +ssh_packet_close(struct ssh *ssh) +{ + ssh_packet_close_internal(ssh, 1); +} + +void +ssh_packet_clear_keys(struct ssh *ssh) +{ + ssh_packet_close_internal(ssh, 0); } /* Sets remote side protocol flags. */ @@ -698,7 +706,7 @@ ssh_packet_start_compression(struct ssh *ssh, int level) { int r; - if (ssh->state->packet_compression && !compat20) + if (ssh->state->packet_compression) return SSH_ERR_INTERNAL_ERROR; ssh->state->packet_compression = 1; if ((r = ssh_packet_init_compression(ssh)) != 0 || @@ -802,136 +810,13 @@ uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) /* NOTREACHED */ } -/* - * Causes any further packets to be encrypted using the given key. The same - * key is used for both sending and reception. However, both directions are - * encrypted independently of each other. - */ - void -ssh_packet_set_encryption_key(struct ssh *ssh, const u_char *key, u_int keylen, int number) +ssh_clear_newkeys(struct ssh *ssh, int mode) { -#ifndef WITH_SSH1 - fatal("no SSH protocol 1 support"); -#else /* WITH_SSH1 */ - struct session_state *state = ssh->state; - const struct sshcipher *cipher = cipher_by_number(number); - int r; - const char *wmsg; - - if (cipher == NULL) - fatal("%s: unknown cipher number %d", __func__, number); - if (keylen < 20) - fatal("%s: keylen too small: %d", __func__, keylen); - if (keylen > SSH_SESSION_KEY_LENGTH) - fatal("%s: keylen too big: %d", __func__, keylen); - memcpy(state->ssh1_key, key, keylen); - state->ssh1_keylen = keylen; - if ((r = cipher_init(&state->send_context, cipher, key, keylen, - NULL, 0, CIPHER_ENCRYPT)) != 0 || - (r = cipher_init(&state->receive_context, cipher, key, keylen, - NULL, 0, CIPHER_DECRYPT) != 0)) - fatal("%s: cipher_init failed: %s", __func__, ssh_err(r)); - if (!state->cipher_warning_done && - ((wmsg = cipher_warning_message(state->send_context)) != NULL || - (wmsg = cipher_warning_message(state->send_context)) != NULL)) { - error("Warning: %s", wmsg); - state->cipher_warning_done = 1; + if (ssh->kex && ssh->kex->newkeys[mode]) { + kex_free_newkeys(ssh->kex->newkeys[mode]); + ssh->kex->newkeys[mode] = NULL; } -#endif /* WITH_SSH1 */ -} - -/* - * Finalizes and sends the packet. If the encryption key has been set, - * encrypts the packet before sending. - */ - -int -ssh_packet_send1(struct ssh *ssh) -{ - struct session_state *state = ssh->state; - u_char buf[8], *cp; - int r, padding, len; - u_int checksum; - - /* - * If using packet compression, compress the payload of the outgoing - * packet. - */ - if (state->packet_compression) { - sshbuf_reset(state->compression_buffer); - /* Skip padding. */ - if ((r = sshbuf_consume(state->outgoing_packet, 8)) != 0) - goto out; - /* padding */ - if ((r = sshbuf_put(state->compression_buffer, - "\0\0\0\0\0\0\0\0", 8)) != 0) - goto out; - if ((r = compress_buffer(ssh, state->outgoing_packet, - state->compression_buffer)) != 0) - goto out; - sshbuf_reset(state->outgoing_packet); - if ((r = sshbuf_putb(state->outgoing_packet, - state->compression_buffer)) != 0) - goto out; - } - /* Compute packet length without padding (add checksum, remove padding). */ - len = sshbuf_len(state->outgoing_packet) + 4 - 8; - - /* Insert padding. Initialized to zero in packet_start1() */ - padding = 8 - len % 8; - if (!cipher_ctx_is_plaintext(state->send_context)) { - cp = sshbuf_mutable_ptr(state->outgoing_packet); - if (cp == NULL) { - r = SSH_ERR_INTERNAL_ERROR; - goto out; - } - arc4random_buf(cp + 8 - padding, padding); - } - if ((r = sshbuf_consume(state->outgoing_packet, 8 - padding)) != 0) - goto out; - - /* Add check bytes. */ - checksum = ssh_crc32(sshbuf_ptr(state->outgoing_packet), - sshbuf_len(state->outgoing_packet)); - POKE_U32(buf, checksum); - if ((r = sshbuf_put(state->outgoing_packet, buf, 4)) != 0) - goto out; - -#ifdef PACKET_DEBUG - fprintf(stderr, "packet_send plain: "); - sshbuf_dump(state->outgoing_packet, stderr); -#endif - - /* Append to output. */ - POKE_U32(buf, len); - if ((r = sshbuf_put(state->output, buf, 4)) != 0) - goto out; - if ((r = sshbuf_reserve(state->output, - sshbuf_len(state->outgoing_packet), &cp)) != 0) - goto out; - if ((r = cipher_crypt(state->send_context, 0, cp, - sshbuf_ptr(state->outgoing_packet), - sshbuf_len(state->outgoing_packet), 0, 0)) != 0) - goto out; - -#ifdef PACKET_DEBUG - fprintf(stderr, "encrypted: "); - sshbuf_dump(state->output, stderr); -#endif - state->p_send.packets++; - state->p_send.bytes += len + - sshbuf_len(state->outgoing_packet); - sshbuf_reset(state->outgoing_packet); - - /* - * Note that the packet is now only buffered in output. It won't be - * actually sent until ssh_packet_write_wait or ssh_packet_write_poll - * is called. - */ - r = 0; - out: - return r; } int @@ -944,45 +829,33 @@ ssh_set_newkeys(struct ssh *ssh, int mode) struct sshcipher_ctx **ccp; struct packet_state *ps; u_int64_t *max_blocks; - const char *wmsg, *dir; + const char *wmsg; int r, crypt_type; debug2("set_newkeys: mode %d", mode); if (mode == MODE_OUT) { - dir = "output"; ccp = &state->send_context; crypt_type = CIPHER_ENCRYPT; ps = &state->p_send; max_blocks = &state->max_blocks_out; } else { - dir = "input"; ccp = &state->receive_context; crypt_type = CIPHER_DECRYPT; ps = &state->p_read; max_blocks = &state->max_blocks_in; } if (state->newkeys[mode] != NULL) { - debug("%s: rekeying after %llu %s blocks" - " (%llu bytes total)", __func__, - (unsigned long long)ps->blocks, dir, - (unsigned long long)ps->bytes); + debug("set_newkeys: rekeying, input %llu bytes %llu blocks, " + "output %llu bytes %llu blocks", + (unsigned long long)state->p_read.bytes, + (unsigned long long)state->p_read.blocks, + (unsigned long long)state->p_send.bytes, + (unsigned long long)state->p_send.blocks); cipher_free(*ccp); *ccp = NULL; - enc = &state->newkeys[mode]->enc; - mac = &state->newkeys[mode]->mac; - comp = &state->newkeys[mode]->comp; - mac_clear(mac); - explicit_bzero(enc->iv, enc->iv_len); - explicit_bzero(enc->key, enc->key_len); - explicit_bzero(mac->key, mac->key_len); - free(enc->name); - free(enc->iv); - free(enc->key); - free(mac->name); - free(mac->key); - free(comp->name); - free(state->newkeys[mode]); + kex_free_newkeys(state->newkeys[mode]); + state->newkeys[mode] = NULL; } /* note that both bytes and the seqnr are not reset */ ps->packets = ps->blocks = 0; @@ -1027,7 +900,8 @@ ssh_set_newkeys(struct ssh *ssh, int mode) } /* * The 2^(blocksize*2) limit is too expensive for 3DES, - * blowfish, etc, so enforce a 1GB limit for small blocksizes. + * so enforce a 1GB limit for small blocksizes. + * See RFC4344 section 3.2. */ if (enc->block_size >= 16) *max_blocks = (u_int64_t)1 << (enc->block_size*2); @@ -1071,7 +945,10 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len) (int64_t)state->rekey_time + state->rekey_interval <= monotime()) return 1; - /* Always rekey when MAX_PACKETS sent in either direction */ + /* + * Always rekey when MAX_PACKETS sent in either direction + * As per RFC4344 section 3.1 we do this after 2^31 packets. + */ if (state->p_send.packets > MAX_PACKETS || state->p_read.packets > MAX_PACKETS) return 1; @@ -1424,13 +1301,6 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p); if (r != 0) break; - if (!compat20 && ( - *typep == SSH_SMSG_SUCCESS - || *typep == SSH_SMSG_FAILURE - || *typep == SSH_CMSG_EOF - || *typep == SSH_CMSG_EXIT_CONFIRMATION)) - if ((r = sshpkt_get_end(ssh)) != 0) - break; /* If we got a packet, return it. */ if (*typep != SSH_MSG_NONE) break; @@ -1524,153 +1394,6 @@ ssh_packet_read_expect(struct ssh *ssh, u_int expected_type) return 0; } -/* Checks if a full packet is available in the data received so far via - * packet_process_incoming. If so, reads the packet; otherwise returns - * SSH_MSG_NONE. This does not wait for data from the connection. - * - * SSH_MSG_DISCONNECT is handled specially here. Also, - * SSH_MSG_IGNORE messages are skipped by this function and are never returned - * to higher levels. - */ - -int -ssh_packet_read_poll1(struct ssh *ssh, u_char *typep) -{ - struct session_state *state = ssh->state; - u_int len, padded_len; - const char *emsg; - const u_char *cp; - u_char *p; - u_int checksum, stored_checksum; - int r; - - *typep = SSH_MSG_NONE; - - /* Check if input size is less than minimum packet size. */ - if (sshbuf_len(state->input) < 4 + 8) - return 0; - /* Get length of incoming packet. */ - len = PEEK_U32(sshbuf_ptr(state->input)); - if (len < 1 + 2 + 2 || len > 256 * 1024) { - if ((r = sshpkt_disconnect(ssh, "Bad packet length %u", - len)) != 0) - return r; - return SSH_ERR_CONN_CORRUPT; - } - padded_len = (len + 8) & ~7; - - /* Check if the packet has been entirely received. */ - if (sshbuf_len(state->input) < 4 + padded_len) - return 0; - - /* The entire packet is in buffer. */ - - /* Consume packet length. */ - if ((r = sshbuf_consume(state->input, 4)) != 0) - goto out; - - /* - * Cryptographic attack detector for ssh - * (C)1998 CORE-SDI, Buenos Aires Argentina - * Ariel Futoransky(futo@core-sdi.com) - */ - if (!cipher_ctx_is_plaintext(state->receive_context)) { - emsg = NULL; - switch (detect_attack(&state->deattack, - sshbuf_ptr(state->input), padded_len)) { - case DEATTACK_OK: - break; - case DEATTACK_DETECTED: - emsg = "crc32 compensation attack detected"; - break; - case DEATTACK_DOS_DETECTED: - emsg = "deattack denial of service detected"; - break; - default: - emsg = "deattack error"; - break; - } - if (emsg != NULL) { - error("%s", emsg); - if ((r = sshpkt_disconnect(ssh, "%s", emsg)) != 0 || - (r = ssh_packet_write_wait(ssh)) != 0) - return r; - return SSH_ERR_CONN_CORRUPT; - } - } - - /* Decrypt data to incoming_packet. */ - sshbuf_reset(state->incoming_packet); - if ((r = sshbuf_reserve(state->incoming_packet, padded_len, &p)) != 0) - goto out; - if ((r = cipher_crypt(state->receive_context, 0, p, - sshbuf_ptr(state->input), padded_len, 0, 0)) != 0) - goto out; - - if ((r = sshbuf_consume(state->input, padded_len)) != 0) - goto out; - -#ifdef PACKET_DEBUG - fprintf(stderr, "read_poll plain: "); - sshbuf_dump(state->incoming_packet, stderr); -#endif - - /* Compute packet checksum. */ - checksum = ssh_crc32(sshbuf_ptr(state->incoming_packet), - sshbuf_len(state->incoming_packet) - 4); - - /* Skip padding. */ - if ((r = sshbuf_consume(state->incoming_packet, 8 - len % 8)) != 0) - goto out; - - /* Test check bytes. */ - if (len != sshbuf_len(state->incoming_packet)) { - error("%s: len %d != sshbuf_len %zd", __func__, - len, sshbuf_len(state->incoming_packet)); - if ((r = sshpkt_disconnect(ssh, "invalid packet length")) != 0 || - (r = ssh_packet_write_wait(ssh)) != 0) - return r; - return SSH_ERR_CONN_CORRUPT; - } - - cp = sshbuf_ptr(state->incoming_packet) + len - 4; - stored_checksum = PEEK_U32(cp); - if (checksum != stored_checksum) { - error("Corrupted check bytes on input"); - if ((r = sshpkt_disconnect(ssh, "connection corrupted")) != 0 || - (r = ssh_packet_write_wait(ssh)) != 0) - return r; - return SSH_ERR_CONN_CORRUPT; - } - if ((r = sshbuf_consume_end(state->incoming_packet, 4)) < 0) - goto out; - - if (state->packet_compression) { - sshbuf_reset(state->compression_buffer); - if ((r = uncompress_buffer(ssh, state->incoming_packet, - state->compression_buffer)) != 0) - goto out; - sshbuf_reset(state->incoming_packet); - if ((r = sshbuf_putb(state->incoming_packet, - state->compression_buffer)) != 0) - goto out; - } - state->p_read.packets++; - state->p_read.bytes += padded_len + 4; - if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0) - goto out; - if (*typep < SSH_MSG_MIN || *typep > SSH_MSG_MAX) { - error("Invalid ssh1 packet type: %d", *typep); - if ((r = sshpkt_disconnect(ssh, "invalid packet type")) != 0 || - (r = ssh_packet_write_wait(ssh)) != 0) - return r; - return SSH_ERR_PROTOCOL_ERROR; - } - r = 0; - out: - return r; -} - static int ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) { @@ -1951,75 +1674,48 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) for (;;) { msg = NULL; - if (compat20) { - r = ssh_packet_read_poll2(ssh, typep, seqnr_p); - if (r != 0) + r = ssh_packet_read_poll2(ssh, typep, seqnr_p); + if (r != 0) + return r; + if (*typep) { + state->keep_alive_timeouts = 0; + DBG(debug("received packet type %d", *typep)); + } + switch (*typep) { + case SSH2_MSG_IGNORE: + debug3("Received SSH2_MSG_IGNORE"); + break; + case SSH2_MSG_DEBUG: + if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || + (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || + (r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { + free(msg); return r; - if (*typep) { - state->keep_alive_timeouts = 0; - DBG(debug("received packet type %d", *typep)); - } - switch (*typep) { - case SSH2_MSG_IGNORE: - debug3("Received SSH2_MSG_IGNORE"); - break; - case SSH2_MSG_DEBUG: - if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || - (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || - (r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { - free(msg); - return r; - } - debug("Remote: %.900s", msg); - free(msg); - break; - case SSH2_MSG_DISCONNECT: - if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || - (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) - return r; - /* Ignore normal client exit notifications */ - do_log2(ssh->state->server_side && - reason == SSH2_DISCONNECT_BY_APPLICATION ? - SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, - "Received disconnect from %s port %d:" - "%u: %.400s", ssh_remote_ipaddr(ssh), - ssh_remote_port(ssh), reason, msg); - free(msg); - return SSH_ERR_DISCONNECTED; - case SSH2_MSG_UNIMPLEMENTED: - if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0) - return r; - debug("Received SSH2_MSG_UNIMPLEMENTED for %u", - seqnr); - break; - default: - return 0; - } - } else { - r = ssh_packet_read_poll1(ssh, typep); - switch (*typep) { - case SSH_MSG_NONE: - return SSH_MSG_NONE; - case SSH_MSG_IGNORE: - break; - case SSH_MSG_DEBUG: - if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0) - return r; - debug("Remote: %.900s", msg); - free(msg); - break; - case SSH_MSG_DISCONNECT: - if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0) - return r; - error("Received disconnect from %s port %d: " - "%.400s", ssh_remote_ipaddr(ssh), - ssh_remote_port(ssh), msg); - free(msg); - return SSH_ERR_DISCONNECTED; - default: - DBG(debug("received packet type %d", *typep)); - return 0; } + debug("Remote: %.900s", msg); + free(msg); + break; + case SSH2_MSG_DISCONNECT: + if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || + (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) + return r; + /* Ignore normal client exit notifications */ + do_log2(ssh->state->server_side && + reason == SSH2_DISCONNECT_BY_APPLICATION ? + SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, + "Received disconnect from %s port %d:" + "%u: %.400s", ssh_remote_ipaddr(ssh), + ssh_remote_port(ssh), reason, msg); + free(msg); + return SSH_ERR_DISCONNECTED; + case SSH2_MSG_UNIMPLEMENTED: + if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0) + return r; + debug("Received SSH2_MSG_UNIMPLEMENTED for %u", + seqnr); + break; + default: + return 0; } } } @@ -2071,27 +1767,19 @@ ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...) va_list args; int r; - if (compat20 && (ssh->compat & SSH_BUG_DEBUG)) + if ((ssh->compat & SSH_BUG_DEBUG)) return; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); - if (compat20) { - if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 || - (r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */ - (r = sshpkt_put_cstring(ssh, buf)) != 0 || - (r = sshpkt_put_cstring(ssh, "")) != 0 || - (r = sshpkt_send(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); - } else { - if ((r = sshpkt_start(ssh, SSH_MSG_DEBUG)) != 0 || - (r = sshpkt_put_cstring(ssh, buf)) != 0 || - (r = sshpkt_send(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); - } - if ((r = ssh_packet_write_wait(ssh)) != 0) + if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 || + (r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */ + (r = sshpkt_put_cstring(ssh, buf)) != 0 || + (r = sshpkt_put_cstring(ssh, "")) != 0 || + (r = sshpkt_send(ssh)) != 0 || + (r = ssh_packet_write_wait(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); } @@ -2116,15 +1804,20 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r) switch (r) { case SSH_ERR_CONN_CLOSED: + ssh_packet_clear_keys(ssh); logdie("Connection closed by %s", remote_id); case SSH_ERR_CONN_TIMEOUT: + ssh_packet_clear_keys(ssh); logdie("Connection %s %s timed out", ssh->state->server_side ? "from" : "to", remote_id); case SSH_ERR_DISCONNECTED: + ssh_packet_clear_keys(ssh); logdie("Disconnected from %s", remote_id); case SSH_ERR_SYSTEM_ERROR: - if (errno == ECONNRESET) + if (errno == ECONNRESET) { + ssh_packet_clear_keys(ssh); logdie("Connection reset by %s", remote_id); + } /* FALLTHROUGH */ case SSH_ERR_NO_CIPHER_ALG_MATCH: case SSH_ERR_NO_MAC_ALG_MATCH: @@ -2132,12 +1825,14 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r) case SSH_ERR_NO_KEX_ALG_MATCH: case SSH_ERR_NO_HOSTKEY_ALG_MATCH: if (ssh && ssh->kex && ssh->kex->failed_choice) { + ssh_packet_clear_keys(ssh); logdie("Unable to negotiate with %s: %s. " "Their offer: %s", remote_id, ssh_err(r), ssh->kex->failed_choice); } /* FALLTHROUGH */ default: + ssh_packet_clear_keys(ssh); logdie("%s%sConnection %s %s: %s", tag != NULL ? tag : "", tag != NULL ? ": " : "", ssh->state->server_side ? "from" : "to", @@ -2302,7 +1997,7 @@ void ssh_packet_set_tos(struct ssh *ssh, int tos) { #ifndef IP_TOS_IS_BROKEN - if (!ssh_packet_connection_is_on_socket(ssh)) + if (!ssh_packet_connection_is_on_socket(ssh) || tos == INT_MAX) return; switch (ssh_packet_connection_af(ssh)) { # ifdef IP_TOS @@ -2395,36 +2090,6 @@ ssh_packet_get_maxsize(struct ssh *ssh) return ssh->state->max_packet_size; } -/* - * 9.2. Ignored Data Message - * - * byte SSH_MSG_IGNORE - * string data - * - * All implementations MUST understand (and ignore) this message at any - * time (after receiving the protocol version). No implementation is - * required to send them. This message can be used as an additional - * protection measure against advanced traffic analysis techniques. - */ -void -ssh_packet_send_ignore(struct ssh *ssh, int nbytes) -{ - u_int32_t rnd = 0; - int r, i; - - if ((r = sshpkt_start(ssh, compat20 ? - SSH2_MSG_IGNORE : SSH_MSG_IGNORE)) != 0 || - (r = sshpkt_put_u32(ssh, nbytes)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); - for (i = 0; i < nbytes; i++) { - if (i % 4 == 0) - rnd = arc4random(); - if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); - rnd >>= 8; - } -} - void ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, u_int32_t seconds) { @@ -2528,9 +2193,7 @@ newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode) return r; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - /* The cipher struct is constant and shared, you export pointer */ if ((r = sshbuf_put_cstring(b, enc->name)) != 0 || - (r = sshbuf_put(b, &enc->cipher, sizeof(enc->cipher))) != 0 || (r = sshbuf_put_u32(b, enc->enabled)) != 0 || (r = sshbuf_put_u32(b, enc->block_size)) != 0 || (r = sshbuf_put_string(b, enc->key, enc->key_len)) != 0 || @@ -2556,54 +2219,22 @@ int ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m) { struct session_state *state = ssh->state; - u_char *p; - size_t slen, rlen; - int r, ssh1cipher; + int r; - if (!compat20) { - ssh1cipher = cipher_ctx_get_number(state->receive_context); - slen = cipher_get_keyiv_len(state->send_context); - rlen = cipher_get_keyiv_len(state->receive_context); - if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 || - (r = sshbuf_put_u32(m, ssh1cipher)) != 0 || - (r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 || - (r = sshbuf_put_u32(m, slen)) != 0 || - (r = sshbuf_reserve(m, slen, &p)) != 0 || - (r = cipher_get_keyiv(state->send_context, p, slen)) != 0 || - (r = sshbuf_put_u32(m, rlen)) != 0 || - (r = sshbuf_reserve(m, rlen, &p)) != 0 || - (r = cipher_get_keyiv(state->receive_context, p, rlen)) != 0) - return r; - } else { - if ((r = kex_to_blob(m, ssh->kex)) != 0 || - (r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 || - (r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 || - (r = sshbuf_put_u64(m, state->rekey_limit)) != 0 || - (r = sshbuf_put_u32(m, state->rekey_interval)) != 0 || - (r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 || - (r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 || - (r = sshbuf_put_u32(m, state->p_send.packets)) != 0 || - (r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 || - (r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 || - (r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 || - (r = sshbuf_put_u32(m, state->p_read.packets)) != 0 || - (r = sshbuf_put_u64(m, state->p_read.bytes)) != 0) - return r; - } - - slen = cipher_get_keycontext(state->send_context, NULL); - rlen = cipher_get_keycontext(state->receive_context, NULL); - if ((r = sshbuf_put_u32(m, slen)) != 0 || - (r = sshbuf_reserve(m, slen, &p)) != 0) - return r; - if (cipher_get_keycontext(state->send_context, p) != (int)slen) - return SSH_ERR_INTERNAL_ERROR; - if ((r = sshbuf_put_u32(m, rlen)) != 0 || - (r = sshbuf_reserve(m, rlen, &p)) != 0) - return r; - if (cipher_get_keycontext(state->receive_context, p) != (int)rlen) - return SSH_ERR_INTERNAL_ERROR; - if ((r = sshbuf_put_stringb(m, state->input)) != 0 || + if ((r = kex_to_blob(m, ssh->kex)) != 0 || + (r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 || + (r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 || + (r = sshbuf_put_u64(m, state->rekey_limit)) != 0 || + (r = sshbuf_put_u32(m, state->rekey_interval)) != 0 || + (r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 || + (r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 || + (r = sshbuf_put_u32(m, state->p_send.packets)) != 0 || + (r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 || + (r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 || + (r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 || + (r = sshbuf_put_u32(m, state->p_read.packets)) != 0 || + (r = sshbuf_put_u64(m, state->p_read.bytes)) != 0 || + (r = sshbuf_put_stringb(m, state->input)) != 0 || (r = sshbuf_put_stringb(m, state->output)) != 0) return r; @@ -2636,12 +2267,15 @@ newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode) comp = &newkey->comp; if ((r = sshbuf_get_cstring(b, &enc->name, NULL)) != 0 || - (r = sshbuf_get(b, &enc->cipher, sizeof(enc->cipher))) != 0 || (r = sshbuf_get_u32(b, (u_int *)&enc->enabled)) != 0 || (r = sshbuf_get_u32(b, &enc->block_size)) != 0 || (r = sshbuf_get_string(b, &enc->key, &keylen)) != 0 || (r = sshbuf_get_string(b, &enc->iv, &ivlen)) != 0) goto out; + if ((enc->cipher = cipher_by_name(enc->name)) == NULL) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } if (cipher_authlen(enc->cipher) == 0) { if ((r = sshbuf_get_cstring(b, &mac->name, NULL)) != 0) goto out; @@ -2659,11 +2293,6 @@ newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode) if ((r = sshbuf_get_u32(b, &comp->type)) != 0 || (r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0) goto out; - if (enc->name == NULL || - cipher_by_name(enc->name) != enc->cipher) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } if (sshbuf_len(b) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; @@ -2728,61 +2357,33 @@ int ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) { struct session_state *state = ssh->state; - const u_char *ssh1key, *ivin, *ivout, *keyin, *keyout, *input, *output; - size_t ssh1keylen, rlen, slen, ilen, olen; + const u_char *input, *output; + size_t ilen, olen; int r; - u_int ssh1cipher = 0; - if (!compat20) { - if ((r = sshbuf_get_u32(m, &state->remote_protocol_flags)) != 0 || - (r = sshbuf_get_u32(m, &ssh1cipher)) != 0 || - (r = sshbuf_get_string_direct(m, &ssh1key, &ssh1keylen)) != 0 || - (r = sshbuf_get_string_direct(m, &ivout, &slen)) != 0 || - (r = sshbuf_get_string_direct(m, &ivin, &rlen)) != 0) - return r; - if (ssh1cipher > INT_MAX) - return SSH_ERR_KEY_UNKNOWN_CIPHER; - ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen, - (int)ssh1cipher); - if (cipher_get_keyiv_len(state->send_context) != (int)slen || - cipher_get_keyiv_len(state->receive_context) != (int)rlen) - return SSH_ERR_INVALID_FORMAT; - if ((r = cipher_set_keyiv(state->send_context, ivout)) != 0 || - (r = cipher_set_keyiv(state->receive_context, ivin)) != 0) - return r; - } else { - if ((r = kex_from_blob(m, &ssh->kex)) != 0 || - (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 || - (r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 || - (r = sshbuf_get_u64(m, &state->rekey_limit)) != 0 || - (r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 || - (r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 || - (r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 || - (r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 || - (r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 || - (r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 || - (r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 || - (r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 || - (r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0) - return r; - /* - * We set the time here so that in post-auth privsep slave we - * count from the completion of the authentication. - */ - state->rekey_time = monotime(); - /* XXX ssh_set_newkeys overrides p_read.packets? XXX */ - if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 || - (r = ssh_set_newkeys(ssh, MODE_OUT)) != 0) - return r; - } - if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 || - (r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0) + if ((r = kex_from_blob(m, &ssh->kex)) != 0 || + (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 || + (r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 || + (r = sshbuf_get_u64(m, &state->rekey_limit)) != 0 || + (r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 || + (r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 || + (r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 || + (r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 || + (r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 || + (r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 || + (r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 || + (r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 || + (r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0) + return r; + /* + * We set the time here so that in post-auth privsep slave we + * count from the completion of the authentication. + */ + state->rekey_time = monotime(); + /* XXX ssh_set_newkeys overrides p_read.packets? XXX */ + if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 || + (r = ssh_set_newkeys(ssh, MODE_OUT)) != 0) return r; - if (cipher_get_keycontext(state->send_context, NULL) != (int)slen || - cipher_get_keycontext(state->receive_context, NULL) != (int)rlen) - return SSH_ERR_INVALID_FORMAT; - cipher_set_keycontext(state->send_context, keyout); - cipher_set_keycontext(state->receive_context, keyin); if ((r = ssh_packet_set_postauth(ssh)) != 0) return r; @@ -2862,13 +2463,6 @@ sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g) } #endif /* OPENSSL_HAS_ECC */ -#ifdef WITH_SSH1 -int -sshpkt_put_bignum1(struct ssh *ssh, const BIGNUM *v) -{ - return sshbuf_put_bignum1(ssh->state->outgoing_packet, v); -} -#endif /* WITH_SSH1 */ int sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v) @@ -2915,6 +2509,12 @@ sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp) return sshbuf_get_string_direct(ssh->state->incoming_packet, valp, lenp); } +int +sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp) +{ + return sshbuf_peek_string_direct(ssh->state->incoming_packet, valp, lenp); +} + int sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp) { @@ -2930,13 +2530,6 @@ sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g) } #endif /* OPENSSL_HAS_ECC */ -#ifdef WITH_SSH1 -int -sshpkt_get_bignum1(struct ssh *ssh, BIGNUM *v) -{ - return sshbuf_get_bignum1(ssh->state->incoming_packet, v); -} -#endif /* WITH_SSH1 */ int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v) @@ -2966,15 +2559,13 @@ sshpkt_ptr(struct ssh *ssh, size_t *lenp) int sshpkt_start(struct ssh *ssh, u_char type) { - u_char buf[9]; - int len; + u_char buf[6]; /* u32 packet length, u8 pad len, u8 type */ DBG(debug("packet_start[%d]", type)); - len = compat20 ? 6 : 9; - memset(buf, 0, len - 1); - buf[len - 1] = type; + memset(buf, 0, sizeof(buf)); + buf[sizeof(buf) - 1] = type; sshbuf_reset(ssh->state->outgoing_packet); - return sshbuf_put(ssh->state->outgoing_packet, buf, len); + return sshbuf_put(ssh->state->outgoing_packet, buf, sizeof(buf)); } static int @@ -3007,6 +2598,37 @@ ssh_packet_send_mux(struct ssh *ssh) return 0; } +/* + * 9.2. Ignored Data Message + * + * byte SSH_MSG_IGNORE + * string data + * + * All implementations MUST understand (and ignore) this message at any + * time (after receiving the protocol version). No implementation is + * required to send them. This message can be used as an additional + * protection measure against advanced traffic analysis techniques. + */ +int +sshpkt_msg_ignore(struct ssh *ssh, u_int nbytes) +{ + u_int32_t rnd = 0; + int r; + u_int i; + + if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || + (r = sshpkt_put_u32(ssh, nbytes)) != 0) + return r; + for (i = 0; i < nbytes; i++) { + if (i % 4 == 0) + rnd = arc4random(); + if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0) + return r; + rnd >>= 8; + } + return 0; +} + /* send it */ int @@ -3014,10 +2636,7 @@ sshpkt_send(struct ssh *ssh) { if (ssh->state && ssh->state->mux) return ssh_packet_send_mux(ssh); - if (compat20) - return ssh_packet_send2(ssh); - else - return ssh_packet_send1(ssh); + return ssh_packet_send2(ssh); } int @@ -3031,19 +2650,12 @@ sshpkt_disconnect(struct ssh *ssh, const char *fmt,...) vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); - if (compat20) { - if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || - (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 || - (r = sshpkt_put_cstring(ssh, buf)) != 0 || - (r = sshpkt_put_cstring(ssh, "")) != 0 || - (r = sshpkt_send(ssh)) != 0) - return r; - } else { - if ((r = sshpkt_start(ssh, SSH_MSG_DISCONNECT)) != 0 || - (r = sshpkt_put_cstring(ssh, buf)) != 0 || - (r = sshpkt_send(ssh)) != 0) - return r; - } + if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || + (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 || + (r = sshpkt_put_cstring(ssh, buf)) != 0 || + (r = sshpkt_put_cstring(ssh, "")) != 0 || + (r = sshpkt_send(ssh)) != 0) + return r; return 0; } diff --git a/packet.h b/packet.h index 0d25b352c73f..40837e9dbceb 100644 --- a/packet.h +++ b/packet.h @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.h,v 1.76 2017/02/03 23:03:33 djm Exp $ */ +/* $OpenBSD: packet.h,v 1.82 2017/09/12 06:32:07 djm Exp $ */ /* * Author: Tatu Ylonen @@ -77,6 +77,12 @@ struct ssh { TAILQ_HEAD(, key_entry) private_keys; TAILQ_HEAD(, key_entry) public_keys; + /* Client/Server authentication context */ + void *authctxt; + + /* Channels context */ + struct ssh_channels *chanctxt; + /* APP data */ void *app_data; }; @@ -93,8 +99,9 @@ void ssh_packet_set_nonblocking(struct ssh *); int ssh_packet_get_connection_in(struct ssh *); int ssh_packet_get_connection_out(struct ssh *); void ssh_packet_close(struct ssh *); -void ssh_packet_set_encryption_key(struct ssh *, const u_char *, u_int, int); void ssh_packet_set_input_hook(struct ssh *, ssh_packet_hook_fn *, void *); +void ssh_packet_clear_keys(struct ssh *); +void ssh_clear_newkeys(struct ssh *, int); int ssh_packet_is_rekeying(struct ssh *); void ssh_packet_set_protocol_flags(struct ssh *, u_int); @@ -112,14 +119,12 @@ int ssh_packet_set_log_preamble(struct ssh *, const char *, ...) int ssh_packet_log_type(u_char); -int ssh_packet_send1(struct ssh *); int ssh_packet_send2_wrapped(struct ssh *); int ssh_packet_send2(struct ssh *); int ssh_packet_read(struct ssh *); int ssh_packet_read_expect(struct ssh *, u_int type); int ssh_packet_read_poll(struct ssh *); -int ssh_packet_read_poll1(struct ssh *, u_char *); int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p); int ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len); int ssh_packet_read_seqnr(struct ssh *, u_char *, u_int32_t *seqnr_p); @@ -141,7 +146,6 @@ int ssh_packet_not_very_much_data_to_write(struct ssh *); int ssh_packet_connection_is_on_socket(struct ssh *); int ssh_packet_remaining(struct ssh *); -void ssh_packet_send_ignore(struct ssh *, int); void tty_make_modes(int, struct termios *); void tty_parse_modes(int, int *); @@ -172,6 +176,7 @@ int sshpkt_disconnect(struct ssh *, const char *fmt, ...) __attribute__((format(printf, 2, 3))); int sshpkt_add_padding(struct ssh *, u_char); void sshpkt_fatal(struct ssh *ssh, const char *tag, int r); +int sshpkt_msg_ignore(struct ssh *, u_int); int sshpkt_put(struct ssh *ssh, const void *v, size_t len); int sshpkt_putb(struct ssh *ssh, const struct sshbuf *b); @@ -182,7 +187,6 @@ int sshpkt_put_string(struct ssh *ssh, const void *v, size_t len); int sshpkt_put_cstring(struct ssh *ssh, const void *v); int sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v); int sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g); -int sshpkt_put_bignum1(struct ssh *ssh, const BIGNUM *v); int sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v); int sshpkt_get(struct ssh *ssh, void *valp, size_t len); @@ -191,9 +195,9 @@ int sshpkt_get_u32(struct ssh *ssh, u_int32_t *valp); int sshpkt_get_u64(struct ssh *ssh, u_int64_t *valp); int sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp); int sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp); +int sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp); int sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp); int sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g); -int sshpkt_get_bignum1(struct ssh *ssh, BIGNUM *v); int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v); int sshpkt_get_end(struct ssh *ssh); const u_char *sshpkt_ptr(struct ssh *, size_t *lenp); diff --git a/pathnames.h b/pathnames.h index a8deb9fc609b..1c221b01b47f 100644 --- a/pathnames.h +++ b/pathnames.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.25 2016/03/31 05:24:06 dtucker Exp $ */ +/* $OpenBSD: pathnames.h,v 1.27 2017/05/05 10:42:49 naddy Exp $ */ /* * Author: Tatu Ylonen @@ -36,7 +36,6 @@ */ #define _PATH_SERVER_CONFIG_FILE SSHDIR "/sshd_config" #define _PATH_HOST_CONFIG_FILE SSHDIR "/ssh_config" -#define _PATH_HOST_KEY_FILE SSHDIR "/ssh_host_key" #define _PATH_HOST_DSA_KEY_FILE SSHDIR "/ssh_host_dsa_key" #define _PATH_HOST_ECDSA_KEY_FILE SSHDIR "/ssh_host_ecdsa_key" #define _PATH_HOST_ED25519_KEY_FILE SSHDIR "/ssh_host_ed25519_key" @@ -72,7 +71,6 @@ * Name of the default file containing client-side authentication key. This * file should only be readable by the user him/herself. */ -#define _PATH_SSH_CLIENT_IDENTITY _PATH_SSH_USER_DIR "/identity" #define _PATH_SSH_CLIENT_ID_DSA _PATH_SSH_USER_DIR "/id_dsa" #define _PATH_SSH_CLIENT_ID_ECDSA _PATH_SSH_USER_DIR "/id_ecdsa" #define _PATH_SSH_CLIENT_ID_RSA _PATH_SSH_USER_DIR "/id_rsa" diff --git a/platform-misc.c b/platform-misc.c new file mode 100644 index 000000000000..3f396704953d --- /dev/null +++ b/platform-misc.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006 Darren Tucker. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#include "openbsd-compat/openbsd-compat.h" + +/* + * return 1 if the specified uid is a uid that may own a system directory + * otherwise 0. + */ +int +platform_sys_dir_uid(uid_t uid) +{ + if (uid == 0) + return 1; +#ifdef PLATFORM_SYS_DIR_UID + if (uid == PLATFORM_SYS_DIR_UID) + return 1; +#endif + return 0; +} diff --git a/platform.c b/platform.c index 973a63e40165..18c7751de9a8 100644 --- a/platform.c +++ b/platform.c @@ -197,19 +197,3 @@ platform_krb5_get_principal_name(const char *pw_name) return NULL; #endif } - -/* - * return 1 if the specified uid is a uid that may own a system directory - * otherwise 0. - */ -int -platform_sys_dir_uid(uid_t uid) -{ - if (uid == 0) - return 1; -#ifdef PLATFORM_SYS_DIR_UID - if (uid == PLATFORM_SYS_DIR_UID) - return 1; -#endif - return 0; -} diff --git a/readconf.c b/readconf.c index 9d59493f0187..f63894f9ca15 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.270 2017/03/10 04:27:32 djm Exp $ */ +/* $OpenBSD: readconf.c,v 1.279 2017/09/21 19:16:53 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -152,7 +152,7 @@ typedef enum { oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts, - oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, + oUsePrivilegedPort, oLogFacility, oLogLevel, oCiphers, oMacs, oPubkeyAuthentication, oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, @@ -163,7 +163,8 @@ typedef enum { oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, - oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, + oTunnel, oTunnelDevice, + oLocalCommand, oPermitLocalCommand, oRemoteCommand, oVisualHostKey, oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, @@ -171,7 +172,7 @@ typedef enum { oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes, oPubkeyAcceptedKeyTypes, oProxyJump, - oIgnoredUnknownOption, oDeprecated, oUnsupported + oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported } OpCodes; /* Textual representations of the tokens. */ @@ -181,6 +182,8 @@ static struct { OpCodes opcode; } keywords[] = { /* Deprecated options */ + { "protocol", oIgnore }, /* NB. silently ignored */ + { "cipher", oDeprecated }, { "fallbacktorsh", oDeprecated }, { "globalknownhostsfile2", oDeprecated }, { "rhostsauthentication", oDeprecated }, @@ -208,15 +211,9 @@ static struct { { "smartcarddevice", oUnsupported }, { "pkcs11provider", oUnsupported }, #endif -#ifdef WITH_SSH1 - { "rsaauthentication", oRSAAuthentication }, - { "rhostsrsaauthentication", oRhostsRSAAuthentication }, - { "compressionlevel", oCompressionLevel }, -# else { "rsaauthentication", oUnsupported }, { "rhostsrsaauthentication", oUnsupported }, { "compressionlevel", oUnsupported }, -#endif { "forwardagent", oForwardAgent }, { "forwardx11", oForwardX11 }, @@ -245,10 +242,8 @@ static struct { { "hostkeyalias", oHostKeyAlias }, { "proxycommand", oProxyCommand }, { "port", oPort }, - { "cipher", oCipher }, { "ciphers", oCiphers }, { "macs", oMacs }, - { "protocol", oProtocol }, { "remoteforward", oRemoteForward }, { "localforward", oLocalForward }, { "user", oUser }, @@ -265,6 +260,7 @@ static struct { { "tcpkeepalive", oTCPKeepAlive }, { "keepalive", oTCPKeepAlive }, /* obsolete */ { "numberofpasswordprompts", oNumberOfPasswordPrompts }, + { "syslogfacility", oLogFacility }, { "loglevel", oLogLevel }, { "dynamicforward", oDynamicForward }, { "preferredauthentications", oPreferredAuthentications }, @@ -289,6 +285,7 @@ static struct { { "tunneldevice", oTunnelDevice }, { "localcommand", oLocalCommand }, { "permitlocalcommand", oPermitLocalCommand }, + { "remotecommand", oRemoteCommand }, { "visualhostkey", oVisualHostKey }, { "kexalgorithms", oKexAlgorithms }, { "ipqos", oIPQoS }, @@ -443,8 +440,8 @@ add_identity_file(Options *options, const char *dir, const char *filename, if (dir == NULL) /* no dir, filename is absolute */ path = xstrdup(filename); - else - (void)xasprintf(&path, "%.100s%.100s", dir, filename); + else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX) + fatal("Identity file path %s too long", path); /* Avoid registering duplicates */ for (i = 0; i < options->num_identity_files; i++) { @@ -754,6 +751,16 @@ static const struct multistate multistate_yesnoask[] = { { "ask", 2 }, { NULL, -1 } }; +static const struct multistate multistate_strict_hostkey[] = { + { "true", SSH_STRICT_HOSTKEY_YES }, + { "false", SSH_STRICT_HOSTKEY_OFF }, + { "yes", SSH_STRICT_HOSTKEY_YES }, + { "no", SSH_STRICT_HOSTKEY_OFF }, + { "ask", SSH_STRICT_HOSTKEY_ASK }, + { "off", SSH_STRICT_HOSTKEY_OFF }, + { "accept-new", SSH_STRICT_HOSTKEY_NEW }, + { NULL, -1 } +}; static const struct multistate multistate_yesnoaskconfirm[] = { { "true", 1 }, { "false", 0 }, @@ -829,7 +836,9 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, char **cpptr, fwdarg[256]; u_int i, *uintptr, max_entries = 0; int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0; + int remotefwd, dynamicfwd; LogLevel *log_level_ptr; + SyslogFacility *log_facility_ptr; long long val64; size_t len; struct Forward fwd; @@ -870,6 +879,8 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, case oBadOption: /* don't panic, but count bad options */ return -1; + case oIgnore: + return 0; case oIgnoredUnknownOption: debug("%s line %d: Ignored unknown option \"%s\"", filename, linenum, keyword); @@ -953,14 +964,6 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, intptr = &options->pubkey_authentication; goto parse_flag; - case oRSAAuthentication: - intptr = &options->rsa_authentication; - goto parse_flag; - - case oRhostsRSAAuthentication: - intptr = &options->rhosts_rsa_authentication; - goto parse_flag; - case oHostbasedAuthentication: intptr = &options->hostbased_authentication; goto parse_flag; @@ -992,7 +995,7 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, case oStrictHostKeyChecking: intptr = &options->strict_host_key_checking; - multistate_ptr = multistate_yesnoask; + multistate_ptr = multistate_strict_hostkey; goto parse_multistate; case oCompression: @@ -1011,10 +1014,6 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, intptr = &options->number_of_password_prompts; goto parse_int; - case oCompressionLevel: - intptr = &options->compression_level; - goto parse_int; - case oRekeyLimit: arg = strdelim(&s); if (!arg || *arg == '\0') @@ -1177,19 +1176,6 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, intptr = &options->connection_attempts; goto parse_int; - case oCipher: - intptr = &options->cipher; - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - value = cipher_number(arg); - if (value == -1) - fatal("%.200s line %d: Bad cipher '%s'.", - filename, linenum, arg ? arg : ""); - if (*activep && *intptr == -1) - *intptr = value; - break; - case oCiphers: arg = strdelim(&s); if (!arg || *arg == '\0') @@ -1240,19 +1226,6 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, *charptr = xstrdup(arg); break; - case oProtocol: - intptr = &options->protocol; - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - value = proto_spec(arg); - if (value == SSH_PROTO_UNKNOWN) - fatal("%.200s line %d: Bad protocol spec '%s'.", - filename, linenum, arg ? arg : ""); - if (*activep && *intptr == SSH_PROTO_UNKNOWN) - *intptr = value; - break; - case oLogLevel: log_level_ptr = &options->log_level; arg = strdelim(&s); @@ -1264,6 +1237,17 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, *log_level_ptr = (LogLevel) value; break; + case oLogFacility: + log_facility_ptr = &options->log_facility; + arg = strdelim(&s); + value = log_facility_number(arg); + if (value == SYSLOG_FACILITY_NOT_SET) + fatal("%.200s line %d: unsupported log facility '%s'", + filename, linenum, arg ? arg : ""); + if (*log_facility_ptr == -1) + *log_facility_ptr = (SyslogFacility) value; + break; + case oLocalForward: case oRemoteForward: case oDynamicForward: @@ -1272,31 +1256,36 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, fatal("%.200s line %d: Missing port argument.", filename, linenum); - if (opcode == oLocalForward || - opcode == oRemoteForward) { + remotefwd = (opcode == oRemoteForward); + dynamicfwd = (opcode == oDynamicForward); + + if (!dynamicfwd) { arg2 = strdelim(&s); - if (arg2 == NULL || *arg2 == '\0') - fatal("%.200s line %d: Missing target argument.", - filename, linenum); - - /* construct a string for parse_forward */ - snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); - } else if (opcode == oDynamicForward) { - strlcpy(fwdarg, arg, sizeof(fwdarg)); + if (arg2 == NULL || *arg2 == '\0') { + if (remotefwd) + dynamicfwd = 1; + else + fatal("%.200s line %d: Missing target " + "argument.", filename, linenum); + } else { + /* construct a string for parse_forward */ + snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, + arg2); + } } + if (dynamicfwd) + strlcpy(fwdarg, arg, sizeof(fwdarg)); - if (parse_forward(&fwd, fwdarg, - opcode == oDynamicForward ? 1 : 0, - opcode == oRemoteForward ? 1 : 0) == 0) + if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) fatal("%.200s line %d: Bad forwarding specification.", filename, linenum); if (*activep) { - if (opcode == oLocalForward || - opcode == oDynamicForward) - add_local_forward(options, &fwd); - else if (opcode == oRemoteForward) + if (remotefwd) { add_remote_forward(options, &fwd); + } else { + add_local_forward(options, &fwd); + } } break; @@ -1469,6 +1458,10 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, intptr = &options->permit_local_command; goto parse_flag; + case oRemoteCommand: + charptr = &options->remote_command; + goto parse_command; + case oVisualHostKey: intptr = &options->visual_host_key; goto parse_flag; @@ -1794,7 +1787,6 @@ initialize_options(Options * options) options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; options->fwd_opts.streamlocal_bind_unlink = -1; options->use_privileged_port = -1; - options->rsa_authentication = -1; options->pubkey_authentication = -1; options->challenge_response_authentication = -1; options->gss_authentication = -1; @@ -1802,25 +1794,21 @@ initialize_options(Options * options) options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; - options->rhosts_rsa_authentication = -1; options->hostbased_authentication = -1; options->batch_mode = -1; options->check_host_ip = -1; options->strict_host_key_checking = -1; options->compression = -1; options->tcp_keep_alive = -1; - options->compression_level = -1; options->port = -1; options->address_family = -1; options->connection_attempts = -1; options->connection_timeout = -1; options->number_of_password_prompts = -1; - options->cipher = -1; options->ciphers = NULL; options->macs = NULL; options->kex_algorithms = NULL; options->hostkeyalgorithms = NULL; - options->protocol = SSH_PROTO_UNKNOWN; options->num_identity_files = 0; options->num_certificate_files = 0; options->hostname = NULL; @@ -1838,6 +1826,7 @@ initialize_options(Options * options) options->num_local_forwards = 0; options->remote_forwards = NULL; options->num_remote_forwards = 0; + options->log_facility = SYSLOG_FACILITY_NOT_SET; options->log_level = SYSLOG_LEVEL_NOT_SET; options->preferred_authentications = NULL; options->bind_address = NULL; @@ -1861,6 +1850,7 @@ initialize_options(Options * options) options->tun_remote = -1; options->local_command = NULL; options->permit_local_command = -1; + options->remote_command = NULL; options->add_keys_to_agent = -1; options->identity_agent = NULL; options->visual_host_key = -1; @@ -1934,8 +1924,6 @@ fill_default_options(Options * options) options->fwd_opts.streamlocal_bind_unlink = 0; if (options->use_privileged_port == -1) options->use_privileged_port = 0; - if (options->rsa_authentication == -1) - options->rsa_authentication = 1; if (options->pubkey_authentication == -1) options->pubkey_authentication = 1; if (options->challenge_response_authentication == -1) @@ -1948,8 +1936,6 @@ fill_default_options(Options * options) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) options->kbd_interactive_authentication = 1; - if (options->rhosts_rsa_authentication == -1) - options->rhosts_rsa_authentication = 0; if (options->hostbased_authentication == -1) options->hostbased_authentication = 0; if (options->batch_mode == -1) @@ -1957,13 +1943,11 @@ fill_default_options(Options * options) if (options->check_host_ip == -1) options->check_host_ip = 1; if (options->strict_host_key_checking == -1) - options->strict_host_key_checking = 2; /* 2 is default */ + options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK; if (options->compression == -1) options->compression = 0; if (options->tcp_keep_alive == -1) options->tcp_keep_alive = 1; - if (options->compression_level == -1) - options->compression_level = 6; if (options->port == -1) options->port = 0; /* Filled in ssh_connect. */ if (options->address_family == -1) @@ -1972,31 +1956,17 @@ fill_default_options(Options * options) options->connection_attempts = 1; if (options->number_of_password_prompts == -1) options->number_of_password_prompts = 3; - /* Selected in ssh_login(). */ - if (options->cipher == -1) - options->cipher = SSH_CIPHER_NOT_SET; /* options->hostkeyalgorithms, default set in myproposals.h */ - if (options->protocol == SSH_PROTO_UNKNOWN) - options->protocol = SSH_PROTO_2; if (options->add_keys_to_agent == -1) options->add_keys_to_agent = 0; if (options->num_identity_files == 0) { - if (options->protocol & SSH_PROTO_1) { - add_identity_file(options, "~/", - _PATH_SSH_CLIENT_IDENTITY, 0); - } - if (options->protocol & SSH_PROTO_2) { - add_identity_file(options, "~/", - _PATH_SSH_CLIENT_ID_RSA, 0); - add_identity_file(options, "~/", - _PATH_SSH_CLIENT_ID_DSA, 0); + add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0); + add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); #ifdef OPENSSL_HAS_ECC - add_identity_file(options, "~/", - _PATH_SSH_CLIENT_ID_ECDSA, 0); + add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0); #endif - add_identity_file(options, "~/", - _PATH_SSH_CLIENT_ID_ED25519, 0); - } + add_identity_file(options, "~/", + _PATH_SSH_CLIENT_ID_ED25519, 0); } if (options->escape_char == -1) options->escape_char = '~'; @@ -2014,6 +1984,8 @@ fill_default_options(Options * options) } if (options->log_level == SYSLOG_LEVEL_NOT_SET) options->log_level = SYSLOG_LEVEL_INFO; + if (options->log_facility == SYSLOG_FACILITY_NOT_SET) + options->log_facility = SYSLOG_FACILITY_USER; if (options->no_host_authentication_for_localhost == - 1) options->no_host_authentication_for_localhost = 0; if (options->identities_only == -1) @@ -2083,6 +2055,7 @@ fill_default_options(Options * options) } \ } while(0) CLEAR_ON_NONE(options->local_command); + CLEAR_ON_NONE(options->remote_command); CLEAR_ON_NONE(options->proxy_command); CLEAR_ON_NONE(options->control_path); CLEAR_ON_NONE(options->revoked_host_keys); @@ -2372,9 +2345,10 @@ fmt_intarg(OpCodes code, int val) case oAddressFamily: return fmt_multistate_int(val, multistate_addressfamily); case oVerifyHostKeyDNS: - case oStrictHostKeyChecking: case oUpdateHostkeys: return fmt_multistate_int(val, multistate_yesnoask); + case oStrictHostKeyChecking: + return fmt_multistate_int(val, multistate_strict_hostkey); case oControlMaster: return fmt_multistate_int(val, multistate_controlmaster); case oTunnel: @@ -2385,17 +2359,6 @@ fmt_intarg(OpCodes code, int val) return fmt_multistate_int(val, multistate_canonicalizehostname); case oFingerprintHash: return ssh_digest_alg_name(val); - case oProtocol: - switch (val) { - case SSH_PROTO_1: - return "1"; - case SSH_PROTO_2: - return "2"; - case (SSH_PROTO_1|SSH_PROTO_2): - return "2,1"; - default: - return "UNKNOWN"; - } default: switch (val) { case 0: @@ -2540,14 +2503,9 @@ dump_client_config(Options *o, const char *host) dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); - dump_cfg_fmtint(oProtocol, o->protocol); dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); dump_cfg_fmtint(oRequestTTY, o->request_tty); -#ifdef WITH_RSA1 - dump_cfg_fmtint(oRhostsRSAAuthentication, o->rhosts_rsa_authentication); - dump_cfg_fmtint(oRSAAuthentication, o->rsa_authentication); -#endif dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); @@ -2559,9 +2517,6 @@ dump_client_config(Options *o, const char *host) /* Integer options */ dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); -#ifdef WITH_SSH1 - dump_cfg_int(oCompressionLevel, o->compression_level); -#endif dump_cfg_int(oConnectionAttempts, o->connection_attempts); dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); @@ -2579,6 +2534,7 @@ dump_client_config(Options *o, const char *host) dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices); dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX); dump_cfg_string(oLocalCommand, o->local_command); + dump_cfg_string(oRemoteCommand, o->remote_command); dump_cfg_string(oLogLevel, log_level_name(o->log_level)); dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC); #ifdef ENABLE_PKCS11 @@ -2631,10 +2587,6 @@ dump_client_config(Options *o, const char *host) printf("\n"); } - /* oCipher */ - if (o->cipher != SSH_CIPHER_NOT_SET) - printf("Cipher %s\n", cipher_name(o->cipher)); - /* oControlPersist */ if (o->control_persist == 0 || o->control_persist_timeout == 0) dump_cfg_fmtint(oControlPersist, o->control_persist); diff --git a/readconf.h b/readconf.h index cef55f71c914..22fe5c1873c3 100644 --- a/readconf.h +++ b/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.117 2016/07/15 00:24:30 djm Exp $ */ +/* $OpenBSD: readconf.h,v 1.123 2017/09/03 23:33:13 djm Exp $ */ /* * Author: Tatu Ylonen @@ -37,9 +37,6 @@ typedef struct { char *xauth_location; /* Location for xauth program */ struct ForwardOptions fwd_opts; /* forwarding options */ int use_privileged_port; /* Don't use privileged port if false. */ - int rhosts_rsa_authentication; /* Try rhosts with RSA - * authentication. */ - int rsa_authentication; /* Try RSA authentication. */ int pubkey_authentication; /* Try ssh2 pubkey authentication. */ int hostbased_authentication; /* ssh2's rhosts_rsa */ int challenge_response_authentication; @@ -54,11 +51,10 @@ typedef struct { int check_host_ip; /* Also keep track of keys for IP address */ int strict_host_key_checking; /* Strict host key checking. */ int compression; /* Compress packets in both directions. */ - int compression_level; /* Compression level 1 (fast) to 9 - * (best). */ int tcp_keep_alive; /* Set SO_KEEPALIVE. */ int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */ int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */ + SyslogFacility log_facility; /* Facility for system logging. */ LogLevel log_level; /* Level for logging. */ int port; /* Port to connect. */ @@ -69,12 +65,10 @@ typedef struct { * aborting connection attempt */ int number_of_password_prompts; /* Max number of password * prompts. */ - int cipher; /* Cipher to use. */ char *ciphers; /* SSH2 ciphers in order of preference. */ char *macs; /* SSH2 macs in order of preference. */ char *hostkeyalgorithms; /* SSH2 server key types in order of preference. */ char *kex_algorithms; /* SSH2 kex methods in order of preference. */ - int protocol; /* Protocol in order of preference. */ char *hostname; /* Real host to connect. */ char *host_key_alias; /* hostname alias for .ssh/known_hosts */ char *proxy_command; /* Proxy command for connecting the host. */ @@ -140,6 +134,7 @@ typedef struct { char *local_command; int permit_local_command; + char *remote_command; int visual_host_key; int request_tty; @@ -195,6 +190,11 @@ typedef struct { #define SSH_UPDATE_HOSTKEYS_YES 1 #define SSH_UPDATE_HOSTKEYS_ASK 2 +#define SSH_STRICT_HOSTKEY_OFF 0 +#define SSH_STRICT_HOSTKEY_NEW 1 +#define SSH_STRICT_HOSTKEY_YES 2 +#define SSH_STRICT_HOSTKEY_ASK 3 + void initialize_options(Options *); void fill_default_options(Options *); void fill_default_options_for_canonicalization(Options *); diff --git a/regress/Makefile b/regress/Makefile index b23496b98417..7d50f9cfa437 100644 --- a/regress/Makefile +++ b/regress/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.94 2016/12/16 03:51:19 dtucker Exp $ +# $OpenBSD: Makefile,v 1.95 2017/06/24 06:35:24 djm Exp $ REGRESS_TARGETS= unit t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t-exec tests: prep $(REGRESS_TARGETS) @@ -79,7 +79,8 @@ LTESTS= connect \ principals-command \ cert-file \ cfginclude \ - allow-deny-users + allow-deny-users \ + authinfo # dhgex \ @@ -89,30 +90,33 @@ INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers #LTESTS= cipher-speed -USERNAME!= id -un +USERNAME= ${LOGNAME} CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ authorized_keys_${USERNAME}.* \ authorized_principals_${USERNAME} \ banner.in banner.out cert_host_key* cert_user_key* \ copy.1 copy.2 data ed25519-agent ed25519-agent* \ - ed25519-agent.pub empty.in expect failed-regress.log \ - failed-ssh.log failed-sshd.log hkr.* host.rsa host.rsa1 \ - host_* host_ca_key* host_krl_* host_revoked_* key.* \ - key.dsa-* key.ecdsa-* key.ed25519-512 key.ed25519-512.pub \ - key.rsa-* keys-command-args kh.* known_hosts \ - known_hosts-cert known_hosts.* krl-* ls.copy modpipe \ - netcat pidfile putty.rsa2 ready regress.log remote_pid \ - revoked-* rsa rsa-agent rsa-agent.pub rsa.pub rsa1 \ - rsa1-agent rsa1-agent.pub rsa1.pub rsa_ssh2_cr.prv \ + ed25519-agent.pub ed25519 ed25519.pub empty.in \ + expect failed-regress.log failed-ssh.log failed-sshd.log \ + hkr.* host.ed25519 host.rsa host.rsa1 host_* \ + host_ca_key* host_krl_* host_revoked_* key.* \ + key.dsa-* key.ecdsa-* key.ed25519-512 \ + key.ed25519-512.pub key.rsa-* keys-command-args kh.* \ + known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \ + modpipe netcat no_identity_config \ + pidfile putty.rsa2 ready regress.log \ + remote_pid revoked-* rsa rsa-agent rsa-agent.pub rsa.pub \ + rsa1 rsa1-agent rsa1-agent.pub rsa1.pub rsa_ssh2_cr.prv \ rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \ scp-ssh-wrapper.scp setuid-allowed sftp-server.log \ sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \ ssh_config ssh_config.* ssh_proxy ssh_proxy_bak \ - ssh_proxy_envpass sshd.log sshd_config sshd_config.orig \ - sshd_proxy sshd_proxy.* sshd_proxy_bak sshd_proxy_orig \ - t10.out t10.out.pub t12.out t12.out.pub t2.out t3.out \ - t6.out1 t6.out2 t7.out t7.out.pub t8.out t8.out.pub \ - t9.out t9.out.pub testdata user_*key* user_ca* user_key* + ssh_proxy_envpass sshd.log sshd_config sshd_config_minimal \ + sshd_config.orig sshd_proxy sshd_proxy.* sshd_proxy_bak \ + sshd_proxy_orig t10.out t10.out.pub t12.out t12.out.pub \ + t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub \ + t8.out t8.out.pub t9.out t9.out.pub testdata \ + user_*key* user_ca* user_key* SUDO_CLEAN+= /var/run/testdata_${USERNAME} /var/run/keycommand_${USERNAME} diff --git a/regress/agent-getpeereid.sh b/regress/agent-getpeereid.sh index 34bced154f72..037a5091493a 100644 --- a/regress/agent-getpeereid.sh +++ b/regress/agent-getpeereid.sh @@ -1,4 +1,4 @@ -# $OpenBSD: agent-getpeereid.sh,v 1.8 2017/01/06 02:51:16 djm Exp $ +# $OpenBSD: agent-getpeereid.sh,v 1.9 2017/09/13 14:58:26 bluhm Exp $ # Placed in the Public Domain. tid="disallow agent attach from other uid" diff --git a/regress/agent-pkcs11.sh b/regress/agent-pkcs11.sh index 3aa20c8b1ee0..db3018b885fe 100755 --- a/regress/agent-pkcs11.sh +++ b/regress/agent-pkcs11.sh @@ -1,4 +1,4 @@ -# $OpenBSD: agent-pkcs11.sh,v 1.2 2015/01/12 11:46:32 djm Exp $ +# $OpenBSD: agent-pkcs11.sh,v 1.3 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="pkcs11 agent test" @@ -53,7 +53,7 @@ else fi trace "pkcs11 connect via agent" - ${SSH} -2 -F $OBJ/ssh_proxy somehost exit 5 + ${SSH} -F $OBJ/ssh_proxy somehost exit 5 r=$? if [ $r -ne 5 ]; then fail "ssh connect failed (exit code $r)" diff --git a/regress/agent.sh b/regress/agent.sh index c5e2794b763c..0baf0c74a288 100644 --- a/regress/agent.sh +++ b/regress/agent.sh @@ -1,4 +1,4 @@ -# $OpenBSD: agent.sh,v 1.11 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: agent.sh,v 1.12 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="simple agent test" @@ -46,28 +46,24 @@ else fi trace "simple connect via agent" - for p in ${SSH_PROTOCOLS}; do - ${SSH} -$p -F $OBJ/ssh_proxy somehost exit 5$p - r=$? - if [ $r -ne 5$p ]; then - fail "ssh connect with protocol $p failed (exit code $r)" - fi - done + ${SSH} -F $OBJ/ssh_proxy somehost exit 52 + r=$? + if [ $r -ne 52 ]; then + fail "ssh connect with failed (exit code $r)" + fi trace "agent forwarding" - for p in ${SSH_PROTOCOLS}; do - ${SSH} -A -$p -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1 - r=$? - if [ $r -ne 0 ]; then - fail "ssh-add -l via agent fwd proto $p failed (exit code $r)" - fi - ${SSH} -A -$p -F $OBJ/ssh_proxy somehost \ - "${SSH} -$p -F $OBJ/ssh_proxy somehost exit 5$p" - r=$? - if [ $r -ne 5$p ]; then - fail "agent fwd proto $p failed (exit code $r)" - fi - done + ${SSH} -A -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then + fail "ssh-add -l via agent fwd failed (exit code $r)" + fi + ${SSH} -A -F $OBJ/ssh_proxy somehost \ + "${SSH} -F $OBJ/ssh_proxy somehost exit 52" + r=$? + if [ $r -ne 52 ]; then + fail "agent fwd failed (exit code $r)" + fi trace "delete all agent keys" ${SSHADD} -D > /dev/null 2>&1 diff --git a/regress/authinfo.sh b/regress/authinfo.sh new file mode 100644 index 000000000000..e725296c90aa --- /dev/null +++ b/regress/authinfo.sh @@ -0,0 +1,17 @@ +# $OpenBSD: authinfo.sh,v 1.1 2017/06/24 06:35:24 djm Exp $ +# Placed in the Public Domain. + +tid="authinfo" + +# Ensure the environment variable doesn't leak when ExposeAuthInfo=no. +verbose "ExposeAuthInfo=no" +env SSH_USER_AUTH=blah ${SSH} -F $OBJ/ssh_proxy x \ + 'test -z "$SSH_USER_AUTH"' || fail "SSH_USER_AUTH present" + +verbose "ExposeAuthInfo=yes" +echo ExposeAuthInfo=yes >> $OBJ/sshd_proxy +${SSH} -F $OBJ/ssh_proxy x \ + 'grep ^publickey "$SSH_USER_AUTH" /dev/null >/dev/null' || + fail "ssh with ExposeAuthInfo failed" + +# XXX test multiple auth and key contents diff --git a/regress/banner.sh b/regress/banner.sh index 0b9c9500749d..0d9654fe247a 100644 --- a/regress/banner.sh +++ b/regress/banner.sh @@ -1,4 +1,4 @@ -# $OpenBSD: banner.sh,v 1.2 2003/10/11 11:49:49 dtucker Exp $ +# $OpenBSD: banner.sh,v 1.3 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="banner" @@ -9,7 +9,7 @@ touch $OBJ/empty.in trace "test missing banner file" verbose "test $tid: missing banner file" -( ${SSH} -2 -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \ +( ${SSH} -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \ cmp $OBJ/empty.in $OBJ/banner.out ) || \ fail "missing banner file" @@ -30,14 +30,14 @@ for s in 0 10 100 1000 10000 100000 ; do trace "test banner size $s" verbose "test $tid: size $s" - ( ${SSH} -2 -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \ + ( ${SSH} -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \ cmp $OBJ/banner.in $OBJ/banner.out ) || \ fail "banner size $s mismatch" done trace "test suppress banner (-q)" verbose "test $tid: suppress banner (-q)" -( ${SSH} -q -2 -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \ +( ${SSH} -q -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \ cmp $OBJ/empty.in $OBJ/banner.out ) || \ fail "suppress banner (-q)" diff --git a/regress/broken-pipe.sh b/regress/broken-pipe.sh index a416f7a3b52c..c69276e27057 100644 --- a/regress/broken-pipe.sh +++ b/regress/broken-pipe.sh @@ -1,15 +1,12 @@ -# $OpenBSD: broken-pipe.sh,v 1.5 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: broken-pipe.sh,v 1.6 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="broken pipe test" -for p in ${SSH_PROTOCOLS}; do - trace "protocol $p" - for i in 1 2 3 4; do - ${SSH} -$p -F $OBJ/ssh_config_config nexthost echo $i 2> /dev/null | true - r=$? - if [ $r -ne 0 ]; then - fail "broken pipe returns $r for protocol $p" - fi - done +for i in 1 2 3 4; do + ${SSH} -F $OBJ/ssh_config_config nexthost echo $i 2> /dev/null | true + r=$? + if [ $r -ne 0 ]; then + fail "broken pipe returns $r" + fi done diff --git a/regress/brokenkeys.sh b/regress/brokenkeys.sh index 3e70c348ac36..9d5a54fa9db5 100644 --- a/regress/brokenkeys.sh +++ b/regress/brokenkeys.sh @@ -1,4 +1,4 @@ -# $OpenBSD: brokenkeys.sh,v 1.1 2004/10/29 23:59:22 djm Exp $ +# $OpenBSD: brokenkeys.sh,v 1.2 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="broken keys" @@ -14,9 +14,9 @@ echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEABTM= bad key" > $KEYS cat ${KEYS}.bak >> ${KEYS} cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER -${SSH} -2 -F $OBJ/ssh_config somehost true +${SSH} -F $OBJ/ssh_config somehost true if [ $? -ne 0 ]; then - fail "ssh connect with protocol $p failed" + fail "ssh connect with failed" fi mv ${KEYS}.bak ${KEYS} diff --git a/regress/cert-file.sh b/regress/cert-file.sh index 43b8e02014ce..8fd62c7730d9 100755 --- a/regress/cert-file.sh +++ b/regress/cert-file.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cert-file.sh,v 1.5 2017/03/11 23:44:16 djm Exp $ +# $OpenBSD: cert-file.sh,v 1.6 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="ssh with certificates" @@ -54,66 +54,64 @@ cat $OBJ/ssh_proxy | grep -v IdentityFile > $OBJ/no_identity_config # XXX: verify that certificate used was what we expect. Needs exposure of # keys via enviornment variable or similar. -for p in ${SSH_PROTOCOLS}; do # Key with no .pub should work - finding the equivalent *-cert.pub. - verbose "protocol $p: identity cert with no plain public file" - ${SSH} -F $OBJ/no_identity_config -oIdentitiesOnly=yes \ - -i $OBJ/user_key3 somehost exit 5$p - [ $? -ne 5$p ] && fail "ssh failed" +verbose "identity cert with no plain public file" +${SSH} -F $OBJ/no_identity_config -oIdentitiesOnly=yes \ + -i $OBJ/user_key3 somehost exit 52 +[ $? -ne 52 ] && fail "ssh failed" - # CertificateFile matching private key with no .pub file should work. - verbose "protocol $p: CertificateFile with no plain public file" - ${SSH} -F $OBJ/no_identity_config -oIdentitiesOnly=yes \ - -oCertificateFile=$OBJ/user_key3-cert.pub \ - -i $OBJ/user_key3 somehost exit 5$p - [ $? -ne 5$p ] && fail "ssh failed" +# CertificateFile matching private key with no .pub file should work. +verbose "CertificateFile with no plain public file" +${SSH} -F $OBJ/no_identity_config -oIdentitiesOnly=yes \ + -oCertificateFile=$OBJ/user_key3-cert.pub \ + -i $OBJ/user_key3 somehost exit 52 +[ $? -ne 52 ] && fail "ssh failed" - # Just keys should fail - verbose "protocol $p: plain keys" - ${SSH} $opts2 somehost exit 5$p - r=$? - if [ $r -eq 5$p ]; then - fail "ssh succeeded with no certs in protocol $p" - fi +# Just keys should fail +verbose "plain keys" +${SSH} $opts2 somehost exit 52 +r=$? +if [ $r -eq 52 ]; then + fail "ssh succeeded with no certs" +fi - # Keys with untrusted cert should fail. - verbose "protocol $p: untrusted cert" - opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_2.pub" - ${SSH} $opts3 somehost exit 5$p - r=$? - if [ $r -eq 5$p ]; then - fail "ssh succeeded with bad cert in protocol $p" - fi +# Keys with untrusted cert should fail. +verbose "untrusted cert" +opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_2.pub" +${SSH} $opts3 somehost exit 52 +r=$? +if [ $r -eq 52 ]; then + fail "ssh succeeded with bad cert" +fi - # Good cert with bad key should fail. - verbose "protocol $p: good cert, bad key" - opts3="$opts -i $OBJ/user_key2" - opts3="$opts3 -oCertificateFile=$OBJ/cert_user_key1_1.pub" - ${SSH} $opts3 somehost exit 5$p - r=$? - if [ $r -eq 5$p ]; then - fail "ssh succeeded with no matching key in protocol $p" - fi +# Good cert with bad key should fail. +verbose "good cert, bad key" +opts3="$opts -i $OBJ/user_key2" +opts3="$opts3 -oCertificateFile=$OBJ/cert_user_key1_1.pub" +${SSH} $opts3 somehost exit 52 +r=$? +if [ $r -eq 52 ]; then + fail "ssh succeeded with no matching key" +fi - # Keys with one trusted cert, should succeed. - verbose "protocol $p: single trusted" - opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_1.pub" - ${SSH} $opts3 somehost exit 5$p - r=$? - if [ $r -ne 5$p ]; then - fail "ssh failed with trusted cert and key in protocol $p" - fi +# Keys with one trusted cert, should succeed. +verbose "single trusted" +opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_1.pub" +${SSH} $opts3 somehost exit 52 +r=$? +if [ $r -ne 52 ]; then + fail "ssh failed with trusted cert and key" +fi - # Multiple certs and keys, with one trusted cert, should succeed. - verbose "protocol $p: multiple trusted" - opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_2.pub" - opts3="$opts3 -oCertificateFile=$OBJ/cert_user_key1_1.pub" - ${SSH} $opts3 somehost exit 5$p - r=$? - if [ $r -ne 5$p ]; then - fail "ssh failed with multiple certs in protocol $p" - fi -done +# Multiple certs and keys, with one trusted cert, should succeed. +verbose "multiple trusted" +opts3="$opts2 -oCertificateFile=$OBJ/cert_user_key1_2.pub" +opts3="$opts3 -oCertificateFile=$OBJ/cert_user_key1_1.pub" +${SSH} $opts3 somehost exit 52 +r=$? +if [ $r -ne 52 ]; then + fail "ssh failed with multiple certs" +fi #next, using an agent in combination with the keys SSH_AUTH_SOCK=/nonexistent ${SSHADD} -l > /dev/null 2>&1 @@ -139,26 +137,25 @@ if [ $? -ne 0 ]; then fi # try ssh with the agent and certificates -# note: ssh agent only uses certificates in protocol 2 opts="-F $OBJ/ssh_proxy" # with no certificates, shoud fail -${SSH} -2 $opts somehost exit 52 +${SSH} $opts somehost exit 52 if [ $? -eq 52 ]; then - fail "ssh connect with agent in protocol 2 succeeded with no cert" + fail "ssh connect with agent in succeeded with no cert" fi #with an untrusted certificate, should fail opts="$opts -oCertificateFile=$OBJ/cert_user_key1_2.pub" -${SSH} -2 $opts somehost exit 52 +${SSH} $opts somehost exit 52 if [ $? -eq 52 ]; then - fail "ssh connect with agent in protocol 2 succeeded with bad cert" + fail "ssh connect with agent in succeeded with bad cert" fi #with an additional trusted certificate, should succeed opts="$opts -oCertificateFile=$OBJ/cert_user_key1_1.pub" -${SSH} -2 $opts somehost exit 52 +${SSH} $opts somehost exit 52 if [ $? -ne 52 ]; then - fail "ssh connect with agent in protocol 2 failed with good cert" + fail "ssh connect with agent in failed with good cert" fi trace "kill agent" diff --git a/regress/cert-hostkey.sh b/regress/cert-hostkey.sh index 62261cf8b3b5..3d5732a5d4fa 100755 --- a/regress/cert-hostkey.sh +++ b/regress/cert-hostkey.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cert-hostkey.sh,v 1.14 2016/05/02 09:52:00 djm Exp $ +# $OpenBSD: cert-hostkey.sh,v 1.15 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="certified host keys" @@ -104,7 +104,7 @@ attempt_connect() { shift; shift verbose "$tid: $_ident expect success $_expect_success" cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert - ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ + ${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ "$@" -F $OBJ/ssh_proxy somehost true _r=$? @@ -169,7 +169,7 @@ for privsep in yes no ; do ) > $OBJ/sshd_proxy cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert - ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ + ${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then @@ -190,7 +190,7 @@ for ktype in $PLAIN_TYPES ; do echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub ) > $OBJ/sshd_proxy cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert - ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ + ${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then @@ -222,7 +222,7 @@ test_one() { ) > $OBJ/sshd_proxy cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert - ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ + ${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 rc=$? @@ -271,7 +271,7 @@ for ktype in $PLAIN_TYPES ; do echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub ) > $OBJ/sshd_proxy - ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ + ${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ -F $OBJ/ssh_proxy somehost true if [ $? -ne 0 ]; then @@ -303,7 +303,7 @@ for kt in $PLAIN_TYPES ; do ) > $OBJ/sshd_proxy cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert - ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ + ${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ -F $OBJ/ssh_proxy -q somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then diff --git a/regress/cert-userkey.sh b/regress/cert-userkey.sh index 7005fd55eb6f..6a23fe300bf7 100755 --- a/regress/cert-userkey.sh +++ b/regress/cert-userkey.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cert-userkey.sh,v 1.17 2016/11/30 03:01:33 djm Exp $ +# $OpenBSD: cert-userkey.sh,v 1.18 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="certified user keys" @@ -67,7 +67,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do # Missing authorized_principals verbose "$tid: ${_prefix} missing authorized_principals" rm -f $OBJ/authorized_principals_$USER - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpectedly" @@ -76,7 +76,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do # Empty authorized_principals verbose "$tid: ${_prefix} empty authorized_principals" echo > $OBJ/authorized_principals_$USER - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpectedly" @@ -85,7 +85,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do # Wrong authorized_principals verbose "$tid: ${_prefix} wrong authorized_principals" echo gregorsamsa > $OBJ/authorized_principals_$USER - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpectedly" @@ -94,7 +94,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do # Correct authorized_principals verbose "$tid: ${_prefix} correct authorized_principals" echo mekmitasdigoat > $OBJ/authorized_principals_$USER - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -ne 0 ]; then fail "ssh cert connect failed" @@ -103,7 +103,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do # authorized_principals with bad key option verbose "$tid: ${_prefix} authorized_principals bad key opt" echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpectedly" @@ -113,7 +113,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do verbose "$tid: ${_prefix} authorized_principals command=false" echo 'command="false" mekmitasdigoat' > \ $OBJ/authorized_principals_$USER - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpectedly" @@ -124,7 +124,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do verbose "$tid: ${_prefix} authorized_principals command=true" echo 'command="true" mekmitasdigoat' > \ $OBJ/authorized_principals_$USER - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost false >/dev/null 2>&1 if [ $? -ne 0 ]; then fail "ssh cert connect failed" @@ -148,7 +148,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do printf 'cert-authority,principals="gregorsamsa" ' cat $OBJ/user_ca_key.pub ) > $OBJ/authorized_keys_$USER - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpectedly" @@ -160,7 +160,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do printf 'cert-authority,principals="mekmitasdigoat" ' cat $OBJ/user_ca_key.pub ) > $OBJ/authorized_keys_$USER - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -ne 0 ]; then fail "ssh cert connect failed" @@ -198,7 +198,7 @@ basic_tests() { echo "PubkeyAcceptedKeyTypes ${t}" ) > $OBJ/ssh_proxy - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true if [ $? -ne 0 ]; then fail "ssh cert connect failed" @@ -215,7 +215,7 @@ basic_tests() { ) > $OBJ/sshd_proxy cp $OBJ/cert_user_key_${ktype}.pub \ $OBJ/cert_user_key_revoked - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpecedly" @@ -224,14 +224,14 @@ basic_tests() { rm $OBJ/cert_user_key_revoked ${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked \ $OBJ/cert_user_key_${ktype}.pub - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpecedly" fi verbose "$tid: ${_prefix} empty KRL" ${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -ne 0 ]; then fail "ssh cert connect failed" @@ -246,7 +246,7 @@ basic_tests() { echo "PubkeyAcceptedKeyTypes ${t}" echo "$extra_sshd" ) > $OBJ/sshd_proxy - ${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \ + ${SSH} -i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \ somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpecedly" @@ -260,7 +260,7 @@ basic_tests() { echo "$extra_sshd" ) > $OBJ/sshd_proxy verbose "$tid: ensure CA key does not authenticate user" - ${SSH} -2i $OBJ/user_ca_key \ + ${SSH} -i $OBJ/user_ca_key \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect with CA key succeeded unexpectedly" @@ -307,7 +307,7 @@ test_one() { $sign_opts $OBJ/cert_user_key_${ktype} || fail "couldn't sign cert_user_key_${ktype}" - ${SSH} -2i $OBJ/cert_user_key_${ktype} \ + ${SSH} -i $OBJ/cert_user_key_${ktype} \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 rc=$? if [ "x$result" = "xsuccess" ] ; then @@ -378,7 +378,7 @@ for ktype in $PLAIN_TYPES ; do -n $USER $OBJ/cert_user_key_${ktype} || fatal "couldn't sign cert_user_key_${ktype}" verbose "$tid: user ${ktype} connect wrong cert" - ${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \ + ${SSH} -i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \ somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect $ident succeeded unexpectedly" diff --git a/regress/cfgmatch.sh b/regress/cfgmatch.sh index 056296398657..2504d04f4c51 100644 --- a/regress/cfgmatch.sh +++ b/regress/cfgmatch.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cfgmatch.sh,v 1.9 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: cfgmatch.sh,v 1.10 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="sshd_config match" @@ -13,7 +13,7 @@ echo "ExitOnForwardFailure=yes" >> $OBJ/ssh_proxy start_client() { rm -f $pidfile - ${SSH} -q -$p $fwd "$@" somehost \ + ${SSH} -q $fwd "$@" somehost \ exec sh -c \'"echo \$\$ > $pidfile; exec sleep 100"\' \ >>$TEST_REGRESS_LOGFILE 2>&1 & client_pid=$! @@ -56,22 +56,18 @@ start_sshd #set -x # Test Match + PermitOpen in sshd_config. This should be permitted -for p in ${SSH_PROTOCOLS}; do - trace "match permitopen localhost proto $p" - start_client -F $OBJ/ssh_config - ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \ - fail "match permitopen permit proto $p" - stop_client -done +trace "match permitopen localhost" +start_client -F $OBJ/ssh_config +${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \ + fail "match permitopen permit" +stop_client # Same but from different source. This should not be permitted -for p in ${SSH_PROTOCOLS}; do - trace "match permitopen proxy proto $p" - start_client -F $OBJ/ssh_proxy - ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \ - fail "match permitopen deny proto $p" - stop_client -done +trace "match permitopen proxy" +start_client -F $OBJ/ssh_proxy +${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true && \ + fail "match permitopen deny" +stop_client # Retry previous with key option, should also be denied. cp /dev/null $OBJ/authorized_keys_$USER @@ -79,23 +75,19 @@ for t in ${SSH_KEYTYPES}; do printf 'permitopen="127.0.0.1:'$PORT'" ' >> $OBJ/authorized_keys_$USER cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER done -for p in ${SSH_PROTOCOLS}; do - trace "match permitopen proxy w/key opts proto $p" - start_client -F $OBJ/ssh_proxy - ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \ - fail "match permitopen deny w/key opt proto $p" - stop_client -done +trace "match permitopen proxy w/key opts" +start_client -F $OBJ/ssh_proxy +${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true && \ + fail "match permitopen deny w/key opt" +stop_client # Test both sshd_config and key options permitting the same dst/port pair. # Should be permitted. -for p in ${SSH_PROTOCOLS}; do - trace "match permitopen localhost proto $p" - start_client -F $OBJ/ssh_config - ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \ - fail "match permitopen permit proto $p" - stop_client -done +trace "match permitopen localhost" +start_client -F $OBJ/ssh_config +${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \ + fail "match permitopen permit" +stop_client cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "PermitOpen 127.0.0.1:1 127.0.0.1:$PORT 127.0.0.2:2" >>$OBJ/sshd_proxy @@ -103,13 +95,11 @@ echo "Match User $USER" >>$OBJ/sshd_proxy echo "PermitOpen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy # Test that a Match overrides a PermitOpen in the global section -for p in ${SSH_PROTOCOLS}; do - trace "match permitopen proxy w/key opts proto $p" - start_client -F $OBJ/ssh_proxy - ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \ - fail "match override permitopen proto $p" - stop_client -done +trace "match permitopen proxy w/key opts" +start_client -F $OBJ/ssh_proxy +${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true && \ + fail "match override permitopen" +stop_client cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "PermitOpen 127.0.0.1:1 127.0.0.1:$PORT 127.0.0.2:2" >>$OBJ/sshd_proxy @@ -118,10 +108,8 @@ echo "PermitOpen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy # Test that a rule that doesn't match doesn't override, plus test a # PermitOpen entry that's not at the start of the list -for p in ${SSH_PROTOCOLS}; do - trace "nomatch permitopen proxy w/key opts proto $p" - start_client -F $OBJ/ssh_proxy - ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \ - fail "nomatch override permitopen proto $p" - stop_client -done +trace "nomatch permitopen proxy w/key opts" +start_client -F $OBJ/ssh_proxy +${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \ + fail "nomatch override permitopen" +stop_client diff --git a/regress/cipher-speed.sh b/regress/cipher-speed.sh index 575dc23411d4..5da95b3a9e70 100644 --- a/regress/cipher-speed.sh +++ b/regress/cipher-speed.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cipher-speed.sh,v 1.13 2015/03/24 20:22:17 markus Exp $ +# $OpenBSD: cipher-speed.sh,v 1.14 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="cipher speed" @@ -12,16 +12,16 @@ getbytes () tries="1 2" for c in `${SSH} -Q cipher`; do n=0; for m in `${SSH} -Q mac`; do - trace "proto 2 cipher $c mac $m" + trace "cipher $c mac $m" for x in $tries; do printf "%-60s" "$c/$m:" ( ${SSH} -o 'compression no' \ - -F $OBJ/ssh_proxy -2 -m $m -c $c somehost \ + -F $OBJ/ssh_proxy -m $m -c $c somehost \ exec sh -c \'"dd of=/dev/null obs=32k"\' \ < ${DATA} ) 2>&1 | getbytes if [ $? -ne 0 ]; then - fail "ssh -2 failed with mac $m cipher $c" + fail "ssh failed with mac $m cipher $c" fi done # No point trying all MACs for AEAD ciphers since they are ignored. @@ -30,22 +30,3 @@ for c in `${SSH} -Q cipher`; do n=0; for m in `${SSH} -Q mac`; do fi n=`expr $n + 1` done; done - -if ssh_version 1; then - ciphers="3des blowfish" -else - ciphers="" -fi -for c in $ciphers; do - trace "proto 1 cipher $c" - for x in $tries; do - printf "%-60s" "$c:" - ( ${SSH} -o 'compression no' \ - -F $OBJ/ssh_proxy -1 -c $c somehost \ - exec sh -c \'"dd of=/dev/null obs=32k"\' \ - < ${DATA} ) 2>&1 | getbytes - if [ $? -ne 0 ]; then - fail "ssh -1 failed with cipher $c" - fi - done -done diff --git a/regress/connect-privsep.sh b/regress/connect-privsep.sh index 81cedc7e5f6d..b6abb65e3566 100644 --- a/regress/connect-privsep.sh +++ b/regress/connect-privsep.sh @@ -1,4 +1,4 @@ -# $OpenBSD: connect-privsep.sh,v 1.8 2016/11/01 13:43:27 tb Exp $ +# $OpenBSD: connect-privsep.sh,v 1.9 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="proxy connect with privsep" @@ -6,23 +6,19 @@ tid="proxy connect with privsep" cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig echo 'UsePrivilegeSeparation yes' >> $OBJ/sshd_proxy -for p in ${SSH_PROTOCOLS}; do - ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true - if [ $? -ne 0 ]; then - fail "ssh privsep+proxyconnect protocol $p failed" - fi -done +${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true +if [ $? -ne 0 ]; then + fail "ssh privsep+proxyconnect failed" +fi cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy echo 'UsePrivilegeSeparation sandbox' >> $OBJ/sshd_proxy -for p in ${SSH_PROTOCOLS}; do - ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true - if [ $? -ne 0 ]; then - # XXX replace this with fail once sandbox has stabilised - warn "ssh privsep/sandbox+proxyconnect protocol $p failed" - fi -done +${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true +if [ $? -ne 0 ]; then + # XXX replace this with fail once sandbox has stabilised + warn "ssh privsep/sandbox+proxyconnect failed" +fi # Because sandbox is sensitive to changes in libc, especially malloc, retest # with every malloc.conf option (and none). @@ -32,10 +28,8 @@ else mopts=`echo $TEST_MALLOC_OPTIONS | sed 's/./& /g'` fi for m in '' $mopts ; do - for p in ${SSH_PROTOCOLS}; do - env MALLOC_OPTIONS="$m" ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true + env MALLOC_OPTIONS="$m" ${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true if [ $? -ne 0 ]; then - fail "ssh privsep/sandbox+proxyconnect protocol $p mopt '$m' failed" + fail "ssh privsep/sandbox+proxyconnect mopt '$m' failed" fi - done done diff --git a/regress/connect.sh b/regress/connect.sh index f0d55d343d8a..1b344b6034e9 100644 --- a/regress/connect.sh +++ b/regress/connect.sh @@ -1,13 +1,11 @@ -# $OpenBSD: connect.sh,v 1.5 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: connect.sh,v 1.6 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="simple connect" start_sshd -for p in ${SSH_PROTOCOLS}; do - ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true - if [ $? -ne 0 ]; then - fail "ssh connect with protocol $p failed" - fi -done +${SSH} -F $OBJ/ssh_config somehost true +if [ $? -ne 0 ]; then + fail "ssh connect with failed" +fi diff --git a/regress/dhgex.sh b/regress/dhgex.sh index e7c5733974a7..61fc178e890c 100755 --- a/regress/dhgex.sh +++ b/regress/dhgex.sh @@ -1,4 +1,4 @@ -# $OpenBSD: dhgex.sh,v 1.3 2015/10/23 02:22:01 dtucker Exp $ +# $OpenBSD: dhgex.sh,v 1.4 2017/05/08 01:52:49 djm Exp $ # Placed in the Public Domain. tid="dhgex" @@ -54,7 +54,6 @@ check() #check 2048 3des-cbc check 3072 `${SSH} -Q cipher | grep 128` -check 3072 arcfour blowfish-cbc check 7680 `${SSH} -Q cipher | grep 192` check 8192 `${SSH} -Q cipher | grep 256` check 8192 rijndael-cbc@lysator.liu.se chacha20-poly1305@openssh.com diff --git a/regress/dynamic-forward.sh b/regress/dynamic-forward.sh index dd67c9639eaf..84f8ee19280a 100644 --- a/regress/dynamic-forward.sh +++ b/regress/dynamic-forward.sh @@ -1,4 +1,4 @@ -# $OpenBSD: dynamic-forward.sh,v 1.11 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: dynamic-forward.sh,v 1.13 2017/09/21 19:18:12 markus Exp $ # Placed in the Public Domain. tid="dynamic forwarding" @@ -17,33 +17,34 @@ trace "will use ProxyCommand $proxycmd" start_sshd -for p in ${SSH_PROTOCOLS}; do +for d in D R; do n=0 error="1" trace "start dynamic forwarding, fork to background" + while [ "$error" -ne 0 -a "$n" -lt 3 ]; do n=`expr $n + 1` - ${SSH} -$p -F $OBJ/ssh_config -f -D $FWDPORT -q \ + ${SSH} -F $OBJ/ssh_config -f -$d $FWDPORT -q \ -oExitOnForwardFailure=yes somehost exec sh -c \ \'"echo \$\$ > $OBJ/remote_pid; exec sleep 444"\' error=$? if [ "$error" -ne 0 ]; then - trace "forward failed proto $p attempt $n err $error" + trace "forward failed attempt $n err $error" sleep $n fi done if [ "$error" -ne 0 ]; then - fatal "failed to start dynamic forwarding proto $p" + fatal "failed to start dynamic forwarding" fi for s in 4 5; do for h in 127.0.0.1 localhost; do - trace "testing ssh protocol $p socks version $s host $h" + trace "testing ssh socks version $s host $h (-$d)" ${SSH} -F $OBJ/ssh_config \ -o "ProxyCommand ${proxycmd}${s} $h $PORT" \ - somehost cat $DATA > $OBJ/ls.copy - test -f $OBJ/ls.copy || fail "failed copy $DATA" - cmp $DATA $OBJ/ls.copy || fail "corrupted copy of $DATA" + somehost cat ${DATA} > ${COPY} + test -f ${COPY} || fail "failed copy ${DATA}" + cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" done done @@ -56,4 +57,5 @@ for p in ${SSH_PROTOCOLS}; do else fail "no pid file: $OBJ/remote_pid" fi + done diff --git a/regress/exit-status.sh b/regress/exit-status.sh index 397d8d732fed..aadf99fb3c8b 100644 --- a/regress/exit-status.sh +++ b/regress/exit-status.sh @@ -1,24 +1,22 @@ -# $OpenBSD: exit-status.sh,v 1.7 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: exit-status.sh,v 1.8 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="remote exit status" -for p in ${SSH_PROTOCOLS}; do - for s in 0 1 4 5 44; do - trace "proto $p status $s" - verbose "test $tid: proto $p status $s" - ${SSH} -$p -F $OBJ/ssh_proxy otherhost exit $s - r=$? - if [ $r -ne $s ]; then - fail "exit code mismatch for protocol $p: $r != $s" - fi +for s in 0 1 4 5 44; do + trace "status $s" + verbose "test $tid: status $s" + ${SSH} -F $OBJ/ssh_proxy otherhost exit $s + r=$? + if [ $r -ne $s ]; then + fail "exit code mismatch for: $r != $s" + fi - # same with early close of stdout/err - ${SSH} -$p -F $OBJ/ssh_proxy -n otherhost \ - exec sh -c \'"sleep 2; exec > /dev/null 2>&1; sleep 3; exit $s"\' - r=$? - if [ $r -ne $s ]; then - fail "exit code (with sleep) mismatch for protocol $p: $r != $s" - fi - done + # same with early close of stdout/err + ${SSH} -F $OBJ/ssh_proxy -n otherhost exec \ + sh -c \'"sleep 2; exec > /dev/null 2>&1; sleep 3; exit $s"\' + r=$? + if [ $r -ne $s ]; then + fail "exit code (with sleep) mismatch for: $r != $s" + fi done diff --git a/regress/forcecommand.sh b/regress/forcecommand.sh index 8a9b090ea5d8..e059f1fdbc61 100644 --- a/regress/forcecommand.sh +++ b/regress/forcecommand.sh @@ -1,4 +1,4 @@ -# $OpenBSD: forcecommand.sh,v 1.3 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: forcecommand.sh,v 1.4 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="forced command" @@ -11,11 +11,8 @@ for t in ${SSH_KEYTYPES}; do cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER done -for p in ${SSH_PROTOCOLS}; do - trace "forced command in key option proto $p" - ${SSH} -$p -F $OBJ/ssh_proxy somehost false \ || - fail "forced command in key proto $p" -done +trace "forced command in key option" +${SSH} -F $OBJ/ssh_proxy somehost false || fail "forced command in key" cp /dev/null $OBJ/authorized_keys_$USER for t in ${SSH_KEYTYPES}; do @@ -26,19 +23,13 @@ done cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "ForceCommand true" >> $OBJ/sshd_proxy -for p in ${SSH_PROTOCOLS}; do - trace "forced command in sshd_config overrides key option proto $p" - ${SSH} -$p -F $OBJ/ssh_proxy somehost false \ || - fail "forced command in key proto $p" -done +trace "forced command in sshd_config overrides key option" +${SSH} -F $OBJ/ssh_proxy somehost false || fail "forced command in key" cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "ForceCommand false" >> $OBJ/sshd_proxy echo "Match User $USER" >> $OBJ/sshd_proxy echo " ForceCommand true" >> $OBJ/sshd_proxy -for p in ${SSH_PROTOCOLS}; do - trace "forced command with match proto $p" - ${SSH} -$p -F $OBJ/ssh_proxy somehost false \ || - fail "forced command in key proto $p" -done +trace "forced command with match" +${SSH} -F $OBJ/ssh_proxy somehost false || fail "forced command in key" diff --git a/regress/forward-control.sh b/regress/forward-control.sh index 91957098f7db..2e9dbb53aa6b 100755 --- a/regress/forward-control.sh +++ b/regress/forward-control.sh @@ -1,4 +1,4 @@ -# $OpenBSD: forward-control.sh,v 1.3 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: forward-control.sh,v 1.4 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="sshd control of local and remote forwarding" @@ -32,13 +32,12 @@ wait_for_process_to_exit() { return 0 } -# usage: check_lfwd protocol Y|N message +# usage: check_lfwd Y|N message check_lfwd() { - _proto=$1 - _expected=$2 - _message=$3 + _expected=$1 + _message=$2 rm -f $READY - ${SSH} -oProtocol=$_proto -F $OBJ/ssh_proxy \ + ${SSH} -F $OBJ/ssh_proxy \ -L$LFWD_PORT:127.0.0.1:$PORT \ -o ExitOnForwardFailure=yes \ -n host exec sh -c \'"sleep 60 & echo \$! > $READY ; wait "\' \ @@ -62,13 +61,12 @@ check_lfwd() { fi } -# usage: check_rfwd protocol Y|N message +# usage: check_rfwd Y|N message check_rfwd() { - _proto=$1 - _expected=$2 - _message=$3 + _expected=$1 + _message=$2 rm -f $READY - ${SSH} -oProtocol=$_proto -F $OBJ/ssh_proxy \ + ${SSH} -F $OBJ/ssh_proxy \ -R$RFWD_PORT:127.0.0.1:$PORT \ -o ExitOnForwardFailure=yes \ -n host exec sh -c \'"sleep 60 & echo \$! > $READY ; wait "\' \ @@ -99,10 +97,8 @@ cp ${OBJ}/sshd_proxy ${OBJ}/sshd_proxy.bak cp ${OBJ}/authorized_keys_${USER} ${OBJ}/authorized_keys_${USER}.bak # Sanity check: ensure the default config allows forwarding -for p in ${SSH_PROTOCOLS} ; do - check_lfwd $p Y "proto $p, default configuration" - check_rfwd $p Y "proto $p, default configuration" -done +check_lfwd Y "default configuration" +check_rfwd Y "default configuration" # Usage: all_tests yes|local|remote|no Y|N Y|N Y|N Y|N Y|N Y|N all_tests() { @@ -115,49 +111,46 @@ all_tests() { _permit_rfwd=$7 _badfwd=127.0.0.1:22 _goodfwd=127.0.0.1:${PORT} - for _proto in ${SSH_PROTOCOLS} ; do - cp ${OBJ}/authorized_keys_${USER}.bak \ - ${OBJ}/authorized_keys_${USER} - _prefix="proto $_proto, AllowTcpForwarding=$_tcpfwd" - # No PermitOpen - ( cat ${OBJ}/sshd_proxy.bak ; - echo "AllowTcpForwarding $_tcpfwd" ) \ - > ${OBJ}/sshd_proxy - check_lfwd $_proto $_plain_lfwd "$_prefix" - check_rfwd $_proto $_plain_rfwd "$_prefix" - # PermitOpen via sshd_config that doesn't match - ( cat ${OBJ}/sshd_proxy.bak ; - echo "AllowTcpForwarding $_tcpfwd" ; - echo "PermitOpen $_badfwd" ) \ - > ${OBJ}/sshd_proxy - check_lfwd $_proto $_nopermit_lfwd "$_prefix, !PermitOpen" - check_rfwd $_proto $_nopermit_rfwd "$_prefix, !PermitOpen" - # PermitOpen via sshd_config that does match - ( cat ${OBJ}/sshd_proxy.bak ; - echo "AllowTcpForwarding $_tcpfwd" ; - echo "PermitOpen $_badfwd $_goodfwd" ) \ - > ${OBJ}/sshd_proxy - # NB. permitopen via authorized_keys should have same - # success/fail as via sshd_config - # permitopen via authorized_keys that doesn't match - sed "s/^/permitopen=\"$_badfwd\" /" \ - < ${OBJ}/authorized_keys_${USER}.bak \ - > ${OBJ}/authorized_keys_${USER} || fatal "sed 1 fail" - ( cat ${OBJ}/sshd_proxy.bak ; - echo "AllowTcpForwarding $_tcpfwd" ) \ - > ${OBJ}/sshd_proxy - check_lfwd $_proto $_nopermit_lfwd "$_prefix, !permitopen" - check_rfwd $_proto $_nopermit_rfwd "$_prefix, !permitopen" - # permitopen via authorized_keys that does match - sed "s/^/permitopen=\"$_badfwd\",permitopen=\"$_goodfwd\" /" \ - < ${OBJ}/authorized_keys_${USER}.bak \ - > ${OBJ}/authorized_keys_${USER} || fatal "sed 2 fail" - ( cat ${OBJ}/sshd_proxy.bak ; - echo "AllowTcpForwarding $_tcpfwd" ) \ - > ${OBJ}/sshd_proxy - check_lfwd $_proto $_permit_lfwd "$_prefix, permitopen" - check_rfwd $_proto $_permit_rfwd "$_prefix, permitopen" - done + cp ${OBJ}/authorized_keys_${USER}.bak ${OBJ}/authorized_keys_${USER} + _prefix="AllowTcpForwarding=$_tcpfwd" + # No PermitOpen + ( cat ${OBJ}/sshd_proxy.bak ; + echo "AllowTcpForwarding $_tcpfwd" ) \ + > ${OBJ}/sshd_proxy + check_lfwd $_plain_lfwd "$_prefix" + check_rfwd $_plain_rfwd "$_prefix" + # PermitOpen via sshd_config that doesn't match + ( cat ${OBJ}/sshd_proxy.bak ; + echo "AllowTcpForwarding $_tcpfwd" ; + echo "PermitOpen $_badfwd" ) \ + > ${OBJ}/sshd_proxy + check_lfwd $_nopermit_lfwd "$_prefix, !PermitOpen" + check_rfwd $_nopermit_rfwd "$_prefix, !PermitOpen" + # PermitOpen via sshd_config that does match + ( cat ${OBJ}/sshd_proxy.bak ; + echo "AllowTcpForwarding $_tcpfwd" ; + echo "PermitOpen $_badfwd $_goodfwd" ) \ + > ${OBJ}/sshd_proxy + # NB. permitopen via authorized_keys should have same + # success/fail as via sshd_config + # permitopen via authorized_keys that doesn't match + sed "s/^/permitopen=\"$_badfwd\" /" \ + < ${OBJ}/authorized_keys_${USER}.bak \ + > ${OBJ}/authorized_keys_${USER} || fatal "sed 1 fail" + ( cat ${OBJ}/sshd_proxy.bak ; + echo "AllowTcpForwarding $_tcpfwd" ) \ + > ${OBJ}/sshd_proxy + check_lfwd $_nopermit_lfwd "$_prefix, !permitopen" + check_rfwd $_nopermit_rfwd "$_prefix, !permitopen" + # permitopen via authorized_keys that does match + sed "s/^/permitopen=\"$_badfwd\",permitopen=\"$_goodfwd\" /" \ + < ${OBJ}/authorized_keys_${USER}.bak \ + > ${OBJ}/authorized_keys_${USER} || fatal "sed 2 fail" + ( cat ${OBJ}/sshd_proxy.bak ; + echo "AllowTcpForwarding $_tcpfwd" ) \ + > ${OBJ}/sshd_proxy + check_lfwd $_permit_lfwd "$_prefix, permitopen" + check_rfwd $_permit_rfwd "$_prefix, permitopen" } # no-permitopen mismatch-permitopen match-permitopen diff --git a/regress/forwarding.sh b/regress/forwarding.sh index 45c596d7db99..39fccba7385a 100644 --- a/regress/forwarding.sh +++ b/regress/forwarding.sh @@ -1,4 +1,4 @@ -# $OpenBSD: forwarding.sh,v 1.19 2017/01/30 05:22:14 djm Exp $ +# $OpenBSD: forwarding.sh,v 1.20 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="local and remote forwarding" @@ -22,30 +22,24 @@ for j in 0 1 2; do last=$a done done -for p in ${SSH_PROTOCOLS}; do - q=`expr 3 - $p` - if ! ssh_version $q; then - q=$p - fi - trace "start forwarding, fork to background" - rm -f $CTL - ${SSH} -S $CTL -M -$p -F $OBJ/ssh_config -f $fwd somehost sleep 10 - trace "transfer over forwarded channels and check result" - ${SSH} -$q -F $OBJ/ssh_config -p$last -o 'ConnectionAttempts=4' \ - somehost cat ${DATA} > ${COPY} - test -s ${COPY} || fail "failed copy of ${DATA}" - cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" +trace "start forwarding, fork to background" +rm -f $CTL +${SSH} -S $CTL -M -F $OBJ/ssh_config -f $fwd somehost sleep 10 - ${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost -done +trace "transfer over forwarded channels and check result" +${SSH} -F $OBJ/ssh_config -p$last -o 'ConnectionAttempts=4' \ + somehost cat ${DATA} > ${COPY} +test -s ${COPY} || fail "failed copy of ${DATA}" +cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" + +${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost -for p in ${SSH_PROTOCOLS}; do for d in L R; do - trace "exit on -$d forward failure, proto $p" + trace "exit on -$d forward failure" # this one should succeed - ${SSH} -$p -F $OBJ/ssh_config \ + ${SSH} -F $OBJ/ssh_config \ -$d ${base}01:127.0.0.1:$PORT \ -$d ${base}02:127.0.0.1:$PORT \ -$d ${base}03:127.0.0.1:$PORT \ @@ -55,7 +49,7 @@ for d in L R; do fatal "connection failed, should not" else # this one should fail - ${SSH} -q -$p -F $OBJ/ssh_config \ + ${SSH} -q -F $OBJ/ssh_config \ -$d ${base}01:127.0.0.1:$PORT \ -$d ${base}02:127.0.0.1:$PORT \ -$d ${base}03:127.0.0.1:$PORT \ @@ -68,82 +62,74 @@ for d in L R; do fi fi done -done -for p in ${SSH_PROTOCOLS}; do - trace "simple clear forwarding proto $p" - ${SSH} -$p -F $OBJ/ssh_config -oClearAllForwardings=yes somehost true +trace "simple clear forwarding" +${SSH} -F $OBJ/ssh_config -oClearAllForwardings=yes somehost true - trace "clear local forward proto $p" - rm -f $CTL - ${SSH} -S $CTL -M -$p -f -F $OBJ/ssh_config -L ${base}01:127.0.0.1:$PORT \ - -oClearAllForwardings=yes somehost sleep 10 - if [ $? != 0 ]; then - fail "connection failed with cleared local forwarding" - else - # this one should fail - ${SSH} -$p -F $OBJ/ssh_config -p ${base}01 somehost true \ - >>$TEST_REGRESS_LOGFILE 2>&1 && \ - fail "local forwarding not cleared" - fi - ${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost - - trace "clear remote forward proto $p" - rm -f $CTL - ${SSH} -S $CTL -M -$p -f -F $OBJ/ssh_config -R ${base}01:127.0.0.1:$PORT \ - -oClearAllForwardings=yes somehost sleep 10 - if [ $? != 0 ]; then - fail "connection failed with cleared remote forwarding" - else - # this one should fail - ${SSH} -$p -F $OBJ/ssh_config -p ${base}01 somehost true \ - >>$TEST_REGRESS_LOGFILE 2>&1 && \ - fail "remote forwarding not cleared" - fi - ${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost -done +trace "clear local forward" +rm -f $CTL +${SSH} -S $CTL -M -f -F $OBJ/ssh_config -L ${base}01:127.0.0.1:$PORT \ + -oClearAllForwardings=yes somehost sleep 10 +if [ $? != 0 ]; then + fail "connection failed with cleared local forwarding" +else + # this one should fail + ${SSH} -F $OBJ/ssh_config -p ${base}01 somehost true \ + >>$TEST_REGRESS_LOGFILE 2>&1 && \ + fail "local forwarding not cleared" +fi +${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost -for p in 2; do - trace "stdio forwarding proto $p" - cmd="${SSH} -$p -F $OBJ/ssh_config" - $cmd -o "ProxyCommand $cmd -q -W localhost:$PORT somehost" \ - somehost true - if [ $? != 0 ]; then - fail "stdio forwarding proto $p" - fi -done +trace "clear remote forward" +rm -f $CTL +${SSH} -S $CTL -M -f -F $OBJ/ssh_config -R ${base}01:127.0.0.1:$PORT \ + -oClearAllForwardings=yes somehost sleep 10 +if [ $? != 0 ]; then + fail "connection failed with cleared remote forwarding" +else + # this one should fail + ${SSH} -F $OBJ/ssh_config -p ${base}01 somehost true \ + >>$TEST_REGRESS_LOGFILE 2>&1 && \ + fail "remote forwarding not cleared" +fi +${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost + +trace "stdio forwarding" +cmd="${SSH} -F $OBJ/ssh_config" +$cmd -o "ProxyCommand $cmd -q -W localhost:$PORT somehost" somehost true +if [ $? != 0 ]; then + fail "stdio forwarding" +fi echo "LocalForward ${base}01 127.0.0.1:$PORT" >> $OBJ/ssh_config echo "RemoteForward ${base}02 127.0.0.1:${base}01" >> $OBJ/ssh_config -for p in ${SSH_PROTOCOLS}; do - trace "config file: start forwarding, fork to background" - rm -f $CTL - ${SSH} -S $CTL -M -$p -F $OBJ/ssh_config -f somehost sleep 10 - trace "config file: transfer over forwarded channels and check result" - ${SSH} -F $OBJ/ssh_config -p${base}02 -o 'ConnectionAttempts=4' \ - somehost cat ${DATA} > ${COPY} - test -s ${COPY} || fail "failed copy of ${DATA}" - cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" +trace "config file: start forwarding, fork to background" +rm -f $CTL +${SSH} -S $CTL -M -F $OBJ/ssh_config -f somehost sleep 10 - ${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost -done +trace "config file: transfer over forwarded channels and check result" +${SSH} -F $OBJ/ssh_config -p${base}02 -o 'ConnectionAttempts=4' \ + somehost cat ${DATA} > ${COPY} +test -s ${COPY} || fail "failed copy of ${DATA}" +cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" -for p in 2; do - trace "transfer over chained unix domain socket forwards and check result" - rm -f $OBJ/unix-[123].fwd - rm -f $CTL $CTL.[123] - ${SSH} -S $CTL -M -f -F $OBJ/ssh_config -R${base}01:[$OBJ/unix-1.fwd] somehost sleep 10 - ${SSH} -S $CTL.1 -M -f -F $OBJ/ssh_config -L[$OBJ/unix-1.fwd]:[$OBJ/unix-2.fwd] somehost sleep 10 - ${SSH} -S $CTL.2 -M -f -F $OBJ/ssh_config -R[$OBJ/unix-2.fwd]:[$OBJ/unix-3.fwd] somehost sleep 10 - ${SSH} -S $CTL.3 -M -f -F $OBJ/ssh_config -L[$OBJ/unix-3.fwd]:127.0.0.1:$PORT somehost sleep 10 - ${SSH} -F $OBJ/ssh_config -p${base}01 -o 'ConnectionAttempts=4' \ - somehost cat ${DATA} > ${COPY} - test -s ${COPY} || fail "failed copy ${DATA}" - cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" +${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost + +trace "transfer over chained unix domain socket forwards and check result" +rm -f $OBJ/unix-[123].fwd +rm -f $CTL $CTL.[123] +${SSH} -S $CTL -M -f -F $OBJ/ssh_config -R${base}01:[$OBJ/unix-1.fwd] somehost sleep 10 +${SSH} -S $CTL.1 -M -f -F $OBJ/ssh_config -L[$OBJ/unix-1.fwd]:[$OBJ/unix-2.fwd] somehost sleep 10 +${SSH} -S $CTL.2 -M -f -F $OBJ/ssh_config -R[$OBJ/unix-2.fwd]:[$OBJ/unix-3.fwd] somehost sleep 10 +${SSH} -S $CTL.3 -M -f -F $OBJ/ssh_config -L[$OBJ/unix-3.fwd]:127.0.0.1:$PORT somehost sleep 10 +${SSH} -F $OBJ/ssh_config -p${base}01 -o 'ConnectionAttempts=4' \ + somehost cat ${DATA} > ${COPY} +test -s ${COPY} || fail "failed copy ${DATA}" +cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" + +${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost +${SSH} -F $OBJ/ssh_config -S $CTL.1 -O exit somehost +${SSH} -F $OBJ/ssh_config -S $CTL.2 -O exit somehost +${SSH} -F $OBJ/ssh_config -S $CTL.3 -O exit somehost - ${SSH} -F $OBJ/ssh_config -S $CTL -O exit somehost - ${SSH} -F $OBJ/ssh_config -S $CTL.1 -O exit somehost - ${SSH} -F $OBJ/ssh_config -S $CTL.2 -O exit somehost - ${SSH} -F $OBJ/ssh_config -S $CTL.3 -O exit somehost -done diff --git a/regress/host-expand.sh b/regress/host-expand.sh index 2a95bfe1b37b..9444f7fb619e 100755 --- a/regress/host-expand.sh +++ b/regress/host-expand.sh @@ -1,4 +1,4 @@ -# $OpenBSD: host-expand.sh,v 1.4 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: host-expand.sh,v 1.5 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="expand %h and %n" @@ -11,9 +11,6 @@ somehost 127.0.0.1 EOE -for p in ${SSH_PROTOCOLS}; do - verbose "test $tid: proto $p" - ${SSH} -F $OBJ/ssh_proxy -$p somehost true >$OBJ/actual - diff $OBJ/expect $OBJ/actual || fail "$tid proto $p" -done +${SSH} -F $OBJ/ssh_proxy somehost true >$OBJ/actual +diff $OBJ/expect $OBJ/actual || fail "$tid" diff --git a/regress/hostkey-agent.sh b/regress/hostkey-agent.sh index 094700da62f7..811b6b9ab25a 100755 --- a/regress/hostkey-agent.sh +++ b/regress/hostkey-agent.sh @@ -1,4 +1,4 @@ -# $OpenBSD: hostkey-agent.sh,v 1.6 2015/07/10 06:23:25 markus Exp $ +# $OpenBSD: hostkey-agent.sh,v 1.7 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="hostkey agent" @@ -40,7 +40,7 @@ for ps in no yes; do cp $OBJ/known_hosts.orig $OBJ/known_hosts SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` if [ $? -ne 0 ]; then - fail "protocol $p privsep=$ps failed" + fail "privsep=$ps failed" fi if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then fail "bad SSH_CONNECTION key type $k privsep=$ps" diff --git a/regress/integrity.sh b/regress/integrity.sh index 1df2924f5f09..3eda40f0a3d3 100755 --- a/regress/integrity.sh +++ b/regress/integrity.sh @@ -1,4 +1,4 @@ -# $OpenBSD: integrity.sh,v 1.20 2017/01/06 02:26:10 dtucker Exp $ +# $OpenBSD: integrity.sh,v 1.23 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="integrity" @@ -46,7 +46,7 @@ for m in $macs; do macopt="-m $m -c aes128-ctr" fi verbose "test $tid: $m @$off" - ${SSH} $macopt -2F $OBJ/ssh_proxy -o "$pxy" \ + ${SSH} $macopt -F $OBJ/ssh_proxy -o "$pxy" \ -oServerAliveInterval=1 -oServerAliveCountMax=30 \ 999.999.999.999 'printf "%4096s" " "' >/dev/null if [ $? -eq 0 ]; then @@ -60,14 +60,16 @@ for m in $macs; do Corrupted?MAC* | *message?authentication?code?incorrect*) emac=`expr $emac + 1`; skip=0;; padding*) epad=`expr $epad + 1`; skip=0;; + *Timeout,?server*) + etmo=`expr $etmo + 1`; skip=0;; *) fail "unexpected error mac $m at $off: $out";; esac done - verbose "test $tid: $ecnt errors: mac $emac padding $epad length $elen" + verbose "test $tid: $ecnt errors: mac $emac padding $epad length $elen timeout $etmo" if [ $emac -eq 0 ]; then fail "$m: no mac errors" fi - expect=`expr $ecnt - $epad - $elen` + expect=`expr $ecnt - $epad - $elen - $etmo` if [ $emac -ne $expect ]; then fail "$m: expected $expect mac errors, got $emac" fi diff --git a/regress/key-options.sh b/regress/key-options.sh index 7a68ad358b76..2adee6833475 100755 --- a/regress/key-options.sh +++ b/regress/key-options.sh @@ -1,4 +1,4 @@ -# $OpenBSD: key-options.sh,v 1.3 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: key-options.sh,v 1.4 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="key options" @@ -8,64 +8,56 @@ authkeys="$OBJ/authorized_keys_${USER}" cp $authkeys $origkeys # Test command= forced command -for p in ${SSH_PROTOCOLS}; do - for c in 'command="echo bar"' 'no-pty,command="echo bar"'; do +for c in 'command="echo bar"' 'no-pty,command="echo bar"'; do sed "s/.*/$c &/" $origkeys >$authkeys - verbose "key option proto $p $c" - r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost echo foo` + verbose "key option $c" + r=`${SSH} -q -F $OBJ/ssh_proxy somehost echo foo` if [ "$r" = "foo" ]; then fail "key option forced command not restricted" fi if [ "$r" != "bar" ]; then fail "key option forced command not executed" fi - done done # Test no-pty sed 's/.*/no-pty &/' $origkeys >$authkeys -for p in ${SSH_PROTOCOLS}; do - verbose "key option proto $p no-pty" - r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost tty` - if [ -f "$r" ]; then - fail "key option failed proto $p no-pty (pty $r)" - fi -done +verbose "key option proto no-pty" +r=`${SSH} -q -F $OBJ/ssh_proxy somehost tty` +if [ -f "$r" ]; then + fail "key option failed no-pty (pty $r)" +fi # Test environment= echo 'PermitUserEnvironment yes' >> $OBJ/sshd_proxy sed 's/.*/environment="FOO=bar" &/' $origkeys >$authkeys -for p in ${SSH_PROTOCOLS}; do - verbose "key option proto $p environment" - r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost 'echo $FOO'` - if [ "$r" != "bar" ]; then - fail "key option environment not set" - fi -done +verbose "key option environment" +r=`${SSH} -q -F $OBJ/ssh_proxy somehost 'echo $FOO'` +if [ "$r" != "bar" ]; then + fail "key option environment not set" +fi # Test from= restriction start_sshd -for p in ${SSH_PROTOCOLS}; do - for f in 127.0.0.1 '127.0.0.0\/8'; do +for f in 127.0.0.1 '127.0.0.0\/8'; do cat $origkeys >$authkeys - ${SSH} -$p -q -F $OBJ/ssh_proxy somehost true + ${SSH} -q -F $OBJ/ssh_proxy somehost true if [ $? -ne 0 ]; then - fail "key option proto $p failed without restriction" + fail "key option failed without restriction" fi sed 's/.*/from="'"$f"'" &/' $origkeys >$authkeys from=`head -1 $authkeys | cut -f1 -d ' '` - verbose "key option proto $p $from" - r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost 'echo true'` + verbose "key option $from" + r=`${SSH} -q -F $OBJ/ssh_proxy somehost 'echo true'` if [ "$r" = "true" ]; then - fail "key option proto $p $from not restricted" + fail "key option $from not restricted" fi - r=`${SSH} -$p -q -F $OBJ/ssh_config somehost 'echo true'` + r=`${SSH} -q -F $OBJ/ssh_config somehost 'echo true'` if [ "$r" != "true" ]; then - fail "key option proto $p $from not allowed but should be" + fail "key option $from not allowed but should be" fi - done done rm -f "$origkeys" diff --git a/regress/keygen-change.sh b/regress/keygen-change.sh index e56185050ddf..8b8acd52fb9f 100644 --- a/regress/keygen-change.sh +++ b/regress/keygen-change.sh @@ -1,4 +1,4 @@ -# $OpenBSD: keygen-change.sh,v 1.5 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: keygen-change.sh,v 1.6 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="change passphrase for key" @@ -7,9 +7,6 @@ S1="secret1" S2="2secret" KEYTYPES=`${SSH} -Q key-plain` -if ssh_version 1; then - KEYTYPES="${KEYTYPES} rsa1" -fi for t in $KEYTYPES; do # generate user key for agent diff --git a/regress/keyscan.sh b/regress/keyscan.sh index f97364b76e7d..3bde1219a605 100644 --- a/regress/keyscan.sh +++ b/regress/keyscan.sh @@ -1,4 +1,4 @@ -# $OpenBSD: keyscan.sh,v 1.5 2015/09/11 03:44:21 djm Exp $ +# $OpenBSD: keyscan.sh,v 1.6 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="keyscan" @@ -9,10 +9,6 @@ rm -f ${OBJ}/host.dsa start_sshd KEYTYPES=`${SSH} -Q key-plain` -if ssh_version 1; then - KEYTYPES="${KEYTYPES} rsa1" -fi - for t in $KEYTYPES; do trace "keyscan type $t" ${SSHKEYSCAN} -t $t -p $PORT 127.0.0.1 127.0.0.1 127.0.0.1 \ diff --git a/regress/keytype.sh b/regress/keytype.sh index 8f697788f865..88b022de4adb 100755 --- a/regress/keytype.sh +++ b/regress/keytype.sh @@ -1,13 +1,8 @@ -# $OpenBSD: keytype.sh,v 1.4 2015/07/10 06:23:25 markus Exp $ +# $OpenBSD: keytype.sh,v 1.5 2017/03/20 22:08:06 djm Exp $ # Placed in the Public Domain. tid="login with different key types" -TIME=`which time 2>/dev/null` -if test ! -x "$TIME"; then - TIME="" -fi - cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak @@ -26,8 +21,8 @@ for kt in $ktypes; do rm -f $OBJ/key.$kt bits=`echo ${kt} | awk -F- '{print $2}'` type=`echo ${kt} | awk -F- '{print $1}'` - printf "keygen $type, $bits bits:\t" - ${TIME} ${SSHKEYGEN} -b $bits -q -N '' -t $type -f $OBJ/key.$kt ||\ + verbose "keygen $type, $bits bits" + ${SSHKEYGEN} -b $bits -q -N '' -t $type -f $OBJ/key.$kt ||\ fail "ssh-keygen for type $type, $bits bits failed" done @@ -63,8 +58,8 @@ for ut in $ktypes; do ) > $OBJ/known_hosts cat $OBJ/key.$ut.pub > $OBJ/authorized_keys_$USER for i in $tries; do - printf "userkey $ut, hostkey ${ht}:\t" - ${TIME} ${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true + verbose "userkey $ut, hostkey ${ht}" + ${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true if [ $? -ne 0 ]; then fail "ssh userkey $ut, hostkey $ht failed" fi diff --git a/regress/localcommand.sh b/regress/localcommand.sh index 220f19a4d48b..5224a16b24d7 100755 --- a/regress/localcommand.sh +++ b/regress/localcommand.sh @@ -1,4 +1,4 @@ -# $OpenBSD: localcommand.sh,v 1.3 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: localcommand.sh,v 1.4 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="localcommand" @@ -6,10 +6,8 @@ tid="localcommand" echo 'PermitLocalCommand yes' >> $OBJ/ssh_proxy echo 'LocalCommand echo foo' >> $OBJ/ssh_proxy -for p in ${SSH_PROTOCOLS}; do - verbose "test $tid: proto $p localcommand" - a=`${SSH} -F $OBJ/ssh_proxy -$p somehost true` - if [ "$a" != "foo" ] ; then - fail "$tid proto $p" - fi -done +verbose "test $tid: proto $p localcommand" +a=`${SSH} -F $OBJ/ssh_proxy somehost true` +if [ "$a" != "foo" ] ; then + fail "$tid proto $p" +fi diff --git a/regress/login-timeout.sh b/regress/login-timeout.sh index 12207fd99ee7..4c2d07dc255d 100644 --- a/regress/login-timeout.sh +++ b/regress/login-timeout.sh @@ -1,4 +1,4 @@ -# $OpenBSD: login-timeout.sh,v 1.8 2016/12/16 01:06:27 dtucker Exp $ +# $OpenBSD: login-timeout.sh,v 1.9 2017/08/07 00:53:51 dtucker Exp $ # Placed in the Public Domain. tid="connect after login grace timeout" @@ -10,23 +10,9 @@ echo "LoginGraceTime 10s" >> $OBJ/sshd_config echo "MaxStartups 1" >> $OBJ/sshd_config start_sshd -(echo SSH-2.0-fake; sleep 60) | telnet 127.0.0.1 ${PORT} >/dev/null 2>&1 & +(echo SSH-2.0-fake; sleep 60) | telnet 127.0.0.1 ${PORT} >/dev/null 2>&1 & sleep 15 ${SSH} -F $OBJ/ssh_config somehost true if [ $? -ne 0 ]; then - fail "ssh connect after login grace timeout failed with privsep" -fi - -stop_sshd - -trace "test login grace without privsep" -echo "UsePrivilegeSeparation no" >> $OBJ/sshd_config -start_sshd -sleep 1 - -(echo SSH-2.0-fake; sleep 60) | telnet 127.0.0.1 ${PORT} >/dev/null 2>&1 & -sleep 15 -${SSH} -F $OBJ/ssh_config somehost true -if [ $? -ne 0 ]; then - fail "ssh connect after login grace timeout failed without privsep" + fail "ssh connect after login grace timeout failed" fi diff --git a/regress/misc/fuzz-harness/Makefile b/regress/misc/fuzz-harness/Makefile new file mode 100644 index 000000000000..8fbfc20c68de --- /dev/null +++ b/regress/misc/fuzz-harness/Makefile @@ -0,0 +1,22 @@ +# NB. libssh and libopenbsd-compat should be built with the same sanitizer opts. +CXX=clang++-3.9 +FUZZ_FLAGS=-fsanitize=address,undefined -fsanitize-coverage=edge +FUZZ_LIBS=-lFuzzer + +CXXFLAGS=-O2 -g -Wall -Wextra -I ../../.. $(FUZZ_FLAGS) +LDFLAGS=-L ../../.. -L ../../../openbsd-compat -g $(FUZZ_FLAGS) +LIBS=-lssh -lopenbsd-compat -lcrypto $(FUZZ_LIBS) + +all: pubkey_fuzz sig_fuzz + +.cc.o: + $(CXX) $(CXXFLAGS) -c $< -o $@ + +pubkey_fuzz: pubkey_fuzz.o + $(CXX) -o $@ pubkey_fuzz.o $(LDFLAGS) $(LIBS) + +sig_fuzz: sig_fuzz.o + $(CXX) -o $@ sig_fuzz.o $(LDFLAGS) $(LIBS) + +clean: + -rm -f *.o pubkey_fuzz sig_fuzz diff --git a/regress/misc/fuzz-harness/README b/regress/misc/fuzz-harness/README new file mode 100644 index 000000000000..ae6fbe75d6b6 --- /dev/null +++ b/regress/misc/fuzz-harness/README @@ -0,0 +1 @@ +This directory contains fuzzing harnesses for use with clang's libfuzzer. diff --git a/regress/misc/fuzz-harness/pubkey_fuzz.cc b/regress/misc/fuzz-harness/pubkey_fuzz.cc new file mode 100644 index 000000000000..8bbc110931b1 --- /dev/null +++ b/regress/misc/fuzz-harness/pubkey_fuzz.cc @@ -0,0 +1,18 @@ +#include +#include +#include + +extern "C" { + +#include "sshkey.h" + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + struct sshkey *k = NULL; + int r = sshkey_from_blob(data, size, &k); + if (r == 0) sshkey_free(k); + return 0; +} + +} // extern + diff --git a/regress/misc/fuzz-harness/sig_fuzz.cc b/regress/misc/fuzz-harness/sig_fuzz.cc new file mode 100644 index 000000000000..0e535b49a5af --- /dev/null +++ b/regress/misc/fuzz-harness/sig_fuzz.cc @@ -0,0 +1,50 @@ +// cc_fuzz_target test for public key parsing. + +#include +#include +#include +#include +#include + +extern "C" { + +#include "includes.h" +#include "sshkey.h" +#include "ssherr.h" + +static struct sshkey *generate_or_die(int type, unsigned bits) { + int r; + struct sshkey *ret; + if ((r = sshkey_generate(type, bits, &ret)) != 0) { + fprintf(stderr, "generate(%d, %u): %s", type, bits, ssh_err(r)); + abort(); + } + return ret; +} + +int LLVMFuzzerTestOneInput(const uint8_t* sig, size_t slen) +{ +#ifdef WITH_OPENSSL + static struct sshkey *rsa = generate_or_die(KEY_RSA, 2048); + static struct sshkey *dsa = generate_or_die(KEY_DSA, 1024); + static struct sshkey *ecdsa256 = generate_or_die(KEY_ECDSA, 256); + static struct sshkey *ecdsa384 = generate_or_die(KEY_ECDSA, 384); + static struct sshkey *ecdsa521 = generate_or_die(KEY_ECDSA, 521); +#endif + static struct sshkey *ed25519 = generate_or_die(KEY_ED25519, 0); + static const char *data = "If everyone started announcing his nose had " + "run away, I don’t know how it would all end"; + static const size_t dlen = strlen(data); + +#ifdef WITH_OPENSSL + sshkey_verify(rsa, sig, slen, (const u_char *)data, dlen, 0); + sshkey_verify(dsa, sig, slen, (const u_char *)data, dlen, 0); + sshkey_verify(ecdsa256, sig, slen, (const u_char *)data, dlen, 0); + sshkey_verify(ecdsa384, sig, slen, (const u_char *)data, dlen, 0); + sshkey_verify(ecdsa521, sig, slen, (const u_char *)data, dlen, 0); +#endif + sshkey_verify(ed25519, sig, slen, (const u_char *)data, dlen, 0); + return 0; +} + +} // extern diff --git a/regress/misc/kexfuzz/Makefile b/regress/misc/kexfuzz/Makefile index 3018b632f0fe..d0aca8dfe7e7 100644 --- a/regress/misc/kexfuzz/Makefile +++ b/regress/misc/kexfuzz/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.1 2016/03/04 02:30:37 djm Exp $ +# $OpenBSD: Makefile,v 1.2 2017/04/17 11:02:31 jsg Exp $ .include .include @@ -49,7 +49,7 @@ CDIAGFLAGS+= -Wswitch CDIAGFLAGS+= -Wtrigraphs CDIAGFLAGS+= -Wuninitialized CDIAGFLAGS+= -Wunused -.if ${COMPILER_VERSION} == "gcc4" +.if ${COMPILER_VERSION:L} != "gcc3" CDIAGFLAGS+= -Wpointer-sign CDIAGFLAGS+= -Wold-style-definition .endif diff --git a/regress/misc/kexfuzz/kexfuzz.c b/regress/misc/kexfuzz/kexfuzz.c index 67058027fe52..3e2c481606c0 100644 --- a/regress/misc/kexfuzz/kexfuzz.c +++ b/regress/misc/kexfuzz/kexfuzz.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexfuzz.c,v 1.3 2016/10/11 21:49:54 djm Exp $ */ +/* $OpenBSD: kexfuzz.c,v 1.4 2017/04/30 23:34:55 djm Exp $ */ /* * Fuzz harness for KEX code * @@ -418,7 +418,7 @@ main(int argc, char **argv) close(fd); /* XXX check that it is a private key */ /* XXX support certificates */ - if (key == NULL || key->type == KEY_UNSPEC || key->type == KEY_RSA1) + if (key == NULL || key->type == KEY_UNSPEC) badusage("Invalid key file (-k flag)"); /* Replace (fuzz) mode */ diff --git a/regress/multiplex.sh b/regress/multiplex.sh index acb9234d9a94..078a53a889e5 100644 --- a/regress/multiplex.sh +++ b/regress/multiplex.sh @@ -1,4 +1,4 @@ -# $OpenBSD: multiplex.sh,v 1.27 2014/12/22 06:14:29 djm Exp $ +# $OpenBSD: multiplex.sh,v 1.28 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. CTL=/tmp/openssh.regress.ctl-sock.$$ @@ -101,7 +101,7 @@ for s in 0 1 4 5 44; do ${SSH} -F $OBJ/ssh_config -S $CTL otherhost exit $s r=$? if [ $r -ne $s ]; then - fail "exit code mismatch for protocol $p: $r != $s" + fail "exit code mismatch: $r != $s" fi # same with early close of stdout/err @@ -110,7 +110,7 @@ for s in 0 1 4 5 44; do exec sh -c \'"sleep 2; exec > /dev/null 2>&1; sleep 3; exit $s"\' r=$? if [ $r -ne $s ]; then - fail "exit code (with sleep) mismatch for protocol $p: $r != $s" + fail "exit code (with sleep) mismatch: $r != $s" fi done diff --git a/regress/principals-command.sh b/regress/principals-command.sh index 9b38eb10543f..bcc68e80bca6 100755 --- a/regress/principals-command.sh +++ b/regress/principals-command.sh @@ -1,4 +1,4 @@ -# $OpenBSD: principals-command.sh,v 1.3 2016/09/26 21:34:38 bluhm Exp $ +# $OpenBSD: principals-command.sh,v 1.4 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="authorized principals command" @@ -78,7 +78,7 @@ if [ -x $PRINCIPALS_COMMAND ]; then # Empty authorized_principals verbose "$tid: ${_prefix} empty authorized_principals" echo > $OBJ/authorized_principals_$USER - ${SSH} -2i $OBJ/cert_user_key \ + ${SSH} -i $OBJ/cert_user_key \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpectedly" @@ -87,7 +87,7 @@ if [ -x $PRINCIPALS_COMMAND ]; then # Wrong authorized_principals verbose "$tid: ${_prefix} wrong authorized_principals" echo gregorsamsa > $OBJ/authorized_principals_$USER - ${SSH} -2i $OBJ/cert_user_key \ + ${SSH} -i $OBJ/cert_user_key \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpectedly" @@ -96,7 +96,7 @@ if [ -x $PRINCIPALS_COMMAND ]; then # Correct authorized_principals verbose "$tid: ${_prefix} correct authorized_principals" echo mekmitasdigoat > $OBJ/authorized_principals_$USER - ${SSH} -2i $OBJ/cert_user_key \ + ${SSH} -i $OBJ/cert_user_key \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -ne 0 ]; then fail "ssh cert connect failed" @@ -105,7 +105,7 @@ if [ -x $PRINCIPALS_COMMAND ]; then # authorized_principals with bad key option verbose "$tid: ${_prefix} authorized_principals bad key opt" echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER - ${SSH} -2i $OBJ/cert_user_key \ + ${SSH} -i $OBJ/cert_user_key \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpectedly" @@ -115,7 +115,7 @@ if [ -x $PRINCIPALS_COMMAND ]; then verbose "$tid: ${_prefix} authorized_principals command=false" echo 'command="false" mekmitasdigoat' > \ $OBJ/authorized_principals_$USER - ${SSH} -2i $OBJ/cert_user_key \ + ${SSH} -i $OBJ/cert_user_key \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpectedly" @@ -125,7 +125,7 @@ if [ -x $PRINCIPALS_COMMAND ]; then verbose "$tid: ${_prefix} authorized_principals command=true" echo 'command="true" mekmitasdigoat' > \ $OBJ/authorized_principals_$USER - ${SSH} -2i $OBJ/cert_user_key \ + ${SSH} -i $OBJ/cert_user_key \ -F $OBJ/ssh_proxy somehost false >/dev/null 2>&1 if [ $? -ne 0 ]; then fail "ssh cert connect failed" @@ -144,7 +144,7 @@ if [ -x $PRINCIPALS_COMMAND ]; then printf 'cert-authority,principals="gregorsamsa" ' cat $OBJ/user_ca_key.pub ) > $OBJ/authorized_keys_$USER - ${SSH} -2i $OBJ/cert_user_key \ + ${SSH} -i $OBJ/cert_user_key \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -eq 0 ]; then fail "ssh cert connect succeeded unexpectedly" @@ -156,7 +156,7 @@ if [ -x $PRINCIPALS_COMMAND ]; then printf 'cert-authority,principals="mekmitasdigoat" ' cat $OBJ/user_ca_key.pub ) > $OBJ/authorized_keys_$USER - ${SSH} -2i $OBJ/cert_user_key \ + ${SSH} -i $OBJ/cert_user_key \ -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 if [ $? -ne 0 ]; then fail "ssh cert connect failed" diff --git a/regress/proto-mismatch.sh b/regress/proto-mismatch.sh index 9e8024beb0f9..6ab28c9a7ad9 100644 --- a/regress/proto-mismatch.sh +++ b/regress/proto-mismatch.sh @@ -1,21 +1,17 @@ -# $OpenBSD: proto-mismatch.sh,v 1.4 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: proto-mismatch.sh,v 1.5 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="protocol version mismatch" mismatch () { - server=$1 client=$2 - banner=`echo ${client} | ${SSHD} -o "Protocol=${server}" -i -f ${OBJ}/sshd_proxy` + banner=`echo ${client} | ${SSHD} -i -f ${OBJ}/sshd_proxy` r=$? trace "sshd prints ${banner}" if [ $r -ne 255 ]; then - fail "sshd prints ${banner} and accepts connect with version ${client}" + fail "sshd prints ${banner} but accepts version ${client}" fi } -mismatch 2 SSH-1.5-HALLO -if ssh_version 1; then - mismatch 1 SSH-2.0-HALLO -fi +mismatch SSH-1.5-HALLO diff --git a/regress/proto-version.sh b/regress/proto-version.sh index cf4946115488..1f33b1f00b77 100644 --- a/regress/proto-version.sh +++ b/regress/proto-version.sh @@ -1,4 +1,4 @@ -# $OpenBSD: proto-version.sh,v 1.5 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: proto-version.sh,v 1.7 2017/06/07 01:48:15 djm Exp $ # Placed in the Public Domain. tid="sshd version with different protocol combinations" @@ -6,9 +6,8 @@ tid="sshd version with different protocol combinations" # we just start sshd in inetd mode and check the banner check_version () { - version=$1 - expect=$2 - banner=`printf '' | ${SSHD} -o "Protocol=${version}" -i -f ${OBJ}/sshd_proxy` + expect=$1 + banner=`printf '' | ${SSHD} -i -f ${OBJ}/sshd_proxy` case ${banner} in SSH-1.99-*) proto=199 @@ -24,13 +23,8 @@ check_version () ;; esac if [ ${expect} -ne ${proto} ]; then - fail "wrong protocol version ${banner} for ${version}" + fail "wrong protocol version ${banner}" fi } -check_version 2 20 -if ssh_version 1; then - check_version 2,1 199 - check_version 1,2 199 - check_version 1 15 -fi +check_version 20 diff --git a/regress/proxy-connect.sh b/regress/proxy-connect.sh index b7a43fabe782..f1b9d9f76bd7 100644 --- a/regress/proxy-connect.sh +++ b/regress/proxy-connect.sh @@ -1,4 +1,4 @@ -# $OpenBSD: proxy-connect.sh,v 1.9 2016/02/17 02:24:17 djm Exp $ +# $OpenBSD: proxy-connect.sh,v 1.10 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="proxy connect" @@ -6,27 +6,22 @@ tid="proxy connect" mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig for ps in no yes; do - cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy - echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy - - for p in ${SSH_PROTOCOLS}; do - for c in no yes; do - verbose "plain username protocol $p privsep=$ps comp=$c" - opts="-$p -oCompression=$c -F $OBJ/ssh_proxy" - SSH_CONNECTION=`${SSH} $opts 999.999.999.999 'echo $SSH_CONNECTION'` - if [ $? -ne 0 ]; then - fail "ssh proxyconnect protocol $p privsep=$ps comp=$c failed" - fi - if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then - fail "bad SSH_CONNECTION protocol $p privsep=$ps comp=$c: " \ - "$SSH_CONNECTION" - fi - done - done + cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy + echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy + for c in no yes; do + verbose "plain username privsep=$ps comp=$c" + opts="-oCompression=$c -F $OBJ/ssh_proxy" + SSH_CONNECTION=`${SSH} $opts 999.999.999.999 'echo $SSH_CONNECTION'` + if [ $? -ne 0 ]; then + fail "ssh proxyconnect privsep=$ps comp=$c failed" + fi + if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then + fail "bad SSH_CONNECTION privsep=$ps comp=$c: " \ + "$SSH_CONNECTION" + fi + done done -for p in ${SSH_PROTOCOLS}; do - verbose "username with style protocol $p" - ${SSH} -$p -F $OBJ/ssh_proxy ${USER}:style@999.999.999.999 true || \ - fail "ssh proxyconnect protocol $p failed" -done +verbose "username with style" +${SSH} -F $OBJ/ssh_proxy ${USER}:style@999.999.999.999 true || \ + fail "ssh proxyconnect failed" diff --git a/regress/putty-ciphers.sh b/regress/putty-ciphers.sh index 9adba674e5c3..419daabbaa75 100755 --- a/regress/putty-ciphers.sh +++ b/regress/putty-ciphers.sh @@ -1,4 +1,4 @@ -# $OpenBSD: putty-ciphers.sh,v 1.5 2016/11/25 03:02:01 dtucker Exp $ +# $OpenBSD: putty-ciphers.sh,v 1.6 2017/05/08 01:52:49 djm Exp $ # Placed in the Public Domain. tid="putty ciphers" @@ -8,7 +8,7 @@ if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then exit 0 fi -for c in aes blowfish 3des arcfour aes128-ctr aes192-ctr aes256-ctr ; do +for c in aes 3des aes128-ctr aes192-ctr aes256-ctr ; do verbose "$tid: cipher $c" cp ${OBJ}/.putty/sessions/localhost_proxy \ ${OBJ}/.putty/sessions/cipher_$c diff --git a/regress/putty-transfer.sh b/regress/putty-transfer.sh index 8eb6ae0c0f11..32c79f9ea4b9 100755 --- a/regress/putty-transfer.sh +++ b/regress/putty-transfer.sh @@ -1,4 +1,4 @@ -# $OpenBSD: putty-transfer.sh,v 1.4 2016/11/25 03:02:01 dtucker Exp $ +# $OpenBSD: putty-transfer.sh,v 1.5 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="putty transfer data" @@ -8,33 +8,30 @@ if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then exit 0 fi -# XXX support protocol 1 too -for p in 2; do - for c in 0 1 ; do - verbose "$tid: proto $p compression $c" +for c in 0 1 ; do + verbose "$tid: compression $c" + rm -f ${COPY} + cp ${OBJ}/.putty/sessions/localhost_proxy \ + ${OBJ}/.putty/sessions/compression_$c + echo "Compression=$c" >> ${OBJ}/.putty/sessions/kex_$k + env HOME=$PWD ${PLINK} -load compression_$c -batch \ + -i putty.rsa cat ${DATA} > ${COPY} + if [ $? -ne 0 ]; then + fail "ssh cat $DATA failed" + fi + cmp ${DATA} ${COPY} || fail "corrupted copy" + + for s in 10 100 1k 32k 64k 128k 256k; do + trace "compression $c dd-size ${s}" rm -f ${COPY} - cp ${OBJ}/.putty/sessions/localhost_proxy \ - ${OBJ}/.putty/sessions/compression_$c - echo "Compression=$c" >> ${OBJ}/.putty/sessions/kex_$k - env HOME=$PWD ${PLINK} -load compression_$c -batch \ - -i putty.rsa$p cat ${DATA} > ${COPY} + dd if=$DATA obs=${s} 2> /dev/null | \ + env HOME=$PWD ${PLINK} -load compression_$c \ + -batch -i putty.rsa \ + "cat > ${COPY}" if [ $? -ne 0 ]; then fail "ssh cat $DATA failed" fi - cmp ${DATA} ${COPY} || fail "corrupted copy" - - for s in 10 100 1k 32k 64k 128k 256k; do - trace "proto $p compression $c dd-size ${s}" - rm -f ${COPY} - dd if=$DATA obs=${s} 2> /dev/null | \ - env HOME=$PWD ${PLINK} -load compression_$c \ - -batch -i putty.rsa$p \ - "cat > ${COPY}" - if [ $? -ne 0 ]; then - fail "ssh cat $DATA failed" - fi - cmp $DATA ${COPY} || fail "corrupted copy" - done + cmp $DATA ${COPY} || fail "corrupted copy" done done rm -f ${COPY} diff --git a/regress/reconfigure.sh b/regress/reconfigure.sh index eecddd3c7302..dd15eddb2a24 100644 --- a/regress/reconfigure.sh +++ b/regress/reconfigure.sh @@ -1,4 +1,4 @@ -# $OpenBSD: reconfigure.sh,v 1.5 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: reconfigure.sh,v 1.6 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="simple connect after reconfigure" @@ -18,12 +18,10 @@ fi start_sshd trace "connect before restart" -for p in ${SSH_PROTOCOLS} ; do - ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true - if [ $? -ne 0 ]; then - fail "ssh connect with protocol $p failed before reconfigure" - fi -done +${SSH} -F $OBJ/ssh_config somehost true +if [ $? -ne 0 ]; then + fail "ssh connect with failed before reconfigure" +fi PID=`$SUDO cat $PIDFILE` rm -f $PIDFILE @@ -39,9 +37,7 @@ done test -f $PIDFILE || fatal "sshd did not restart" trace "connect after restart" -for p in ${SSH_PROTOCOLS} ; do - ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true - if [ $? -ne 0 ]; then - fail "ssh connect with protocol $p failed after reconfigure" - fi -done +${SSH} -F $OBJ/ssh_config somehost true +if [ $? -ne 0 ]; then + fail "ssh connect with failed after reconfigure" +fi diff --git a/regress/reexec.sh b/regress/reexec.sh index 72957d4cd263..2192456cd85e 100644 --- a/regress/reexec.sh +++ b/regress/reexec.sh @@ -1,4 +1,4 @@ -# $OpenBSD: reexec.sh,v 1.10 2016/12/16 01:06:27 dtucker Exp $ +# $OpenBSD: reexec.sh,v 1.12 2017/08/07 03:52:55 dtucker Exp $ # Placed in the Public Domain. tid="reexec tests" @@ -19,16 +19,13 @@ start_sshd_copy () copy_tests () { rm -f ${COPY} - for p in ${SSH_PROTOCOLS} ; do - verbose "$tid: proto $p" - ${SSH} -nqo "Protocol=$p" -F $OBJ/ssh_config somehost \ - cat ${DATA} > ${COPY} - if [ $? -ne 0 ]; then - fail "ssh cat $DATA failed" - fi - cmp ${DATA} ${COPY} || fail "corrupted copy" - rm -f ${COPY} - done + ${SSH} -nq -F $OBJ/ssh_config somehost \ + cat ${DATA} > ${COPY} + if [ $? -ne 0 ]; then + fail "ssh cat $DATA failed" + fi + cmp ${DATA} ${COPY} || fail "corrupted copy" + rm -f ${COPY} } verbose "test config passing" @@ -54,17 +51,4 @@ rm -f $SSHD_COPY copy_tests stop_sshd - -verbose "test reexec fallback without privsep" - -cp $OBJ/sshd_config.orig $OBJ/sshd_config -echo "UsePrivilegeSeparation=no" >> $OBJ/sshd_config - -start_sshd_copy -rm -f $SSHD_COPY - -copy_tests - -stop_sshd - fi diff --git a/regress/ssh-com.sh b/regress/ssh-com.sh index 4371d5279746..b1a2505d1135 100644 --- a/regress/ssh-com.sh +++ b/regress/ssh-com.sh @@ -1,4 +1,4 @@ -# $OpenBSD: ssh-com.sh,v 1.9 2015/05/08 07:29:00 djm Exp $ +# $OpenBSD: ssh-com.sh,v 1.10 2017/05/08 01:52:49 djm Exp $ # Placed in the Public Domain. tid="connect to ssh.com server" @@ -87,7 +87,7 @@ for v in ${VERSIONS}; do fail "ssh connect to sshd2 ${v} failed" fi - ciphers="3des-cbc blowfish-cbc arcfour" + ciphers="3des-cbc" macs="hmac-md5" case $v in 2.4.*) diff --git a/regress/stderr-after-eof.sh b/regress/stderr-after-eof.sh index 218ac6b68e19..9065245e84fb 100644 --- a/regress/stderr-after-eof.sh +++ b/regress/stderr-after-eof.sh @@ -1,4 +1,4 @@ -# $OpenBSD: stderr-after-eof.sh,v 1.2 2013/05/17 04:29:14 dtucker Exp $ +# $OpenBSD: stderr-after-eof.sh,v 1.3 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="stderr data after eof" @@ -10,7 +10,7 @@ for i in 1 2 3 4 5 6; do (date;echo $i) | md5 >> ${DATA} done -${SSH} -2 -F $OBJ/ssh_proxy otherhost \ +${SSH} -F $OBJ/ssh_proxy otherhost \ exec sh -c \'"exec > /dev/null; sleep 2; cat ${DATA} 1>&2 $s"\' \ 2> ${COPY} r=$? diff --git a/regress/stderr-data.sh b/regress/stderr-data.sh index 8c8149a732b7..0ceb72b3a298 100644 --- a/regress/stderr-data.sh +++ b/regress/stderr-data.sh @@ -1,13 +1,12 @@ -# $OpenBSD: stderr-data.sh,v 1.4 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: stderr-data.sh,v 1.5 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="stderr data transfer" for n in '' -n; do -for p in ${SSH_PROTOCOLS}; do - verbose "test $tid: proto $p ($n)" - ${SSH} $n -$p -F $OBJ/ssh_proxy otherhost \ - exec sh -c \'"exec > /dev/null; sleep 3; cat ${DATA} 1>&2 $s"\' \ + verbose "test $tid: ($n)" + ${SSH} $n -F $OBJ/ssh_proxy otherhost exec \ + sh -c \'"exec > /dev/null; sleep 3; cat ${DATA} 1>&2 $s"\' \ 2> ${COPY} r=$? if [ $r -ne 0 ]; then @@ -16,8 +15,8 @@ for p in ${SSH_PROTOCOLS}; do cmp ${DATA} ${COPY} || fail "stderr corrupt" rm -f ${COPY} - ${SSH} $n -$p -F $OBJ/ssh_proxy otherhost \ - exec sh -c \'"echo a; exec > /dev/null; sleep 3; cat ${DATA} 1>&2 $s"\' \ + ${SSH} $n -F $OBJ/ssh_proxy otherhost exec \ + sh -c \'"echo a; exec > /dev/null; sleep 3; cat ${DATA} 1>&2 $s"\' \ > /dev/null 2> ${COPY} r=$? if [ $r -ne 0 ]; then @@ -26,4 +25,3 @@ for p in ${SSH_PROTOCOLS}; do cmp ${DATA} ${COPY} || fail "stderr corrupt" rm -f ${COPY} done -done diff --git a/regress/test-exec.sh b/regress/test-exec.sh index dc033cd96203..68f010b70ddc 100644 --- a/regress/test-exec.sh +++ b/regress/test-exec.sh @@ -1,4 +1,4 @@ -# $OpenBSD: test-exec.sh,v 1.59 2017/02/07 23:03:11 dtucker Exp $ +# $OpenBSD: test-exec.sh,v 1.61 2017/07/28 10:32:08 dtucker Exp $ # Placed in the Public Domain. #SUDO=sudo @@ -130,12 +130,6 @@ if [ "x$TEST_SSH_CONCH" != "x" ]; then esac fi -SSH_PROTOCOLS=2 -#SSH_PROTOCOLS=`$SSH -Q protocol-version` -if [ "x$TEST_SSH_PROTOCOLS" != "x" ]; then - SSH_PROTOCOLS="${TEST_SSH_PROTOCOLS}" -fi - # Path to sshd must be absolute for rexec case "$SSHD" in /*) ;; @@ -310,8 +304,15 @@ stop_sshd () i=`expr $i + 1` sleep $i done - test -f $PIDFILE && \ - fatal "sshd didn't exit port $PORT pid $pid" + if test -f $PIDFILE; then + if $SUDO kill -0 $pid; then + echo "sshd didn't exit " \ + "port $PORT pid $pid" + else + echo "sshd died without cleanup" + fi + exit 1 + fi fi fi fi @@ -386,22 +387,11 @@ fatal () exit $RESULT } -ssh_version () -{ - echo ${SSH_PROTOCOLS} | grep "$1" >/dev/null -} - RESULT=0 PIDFILE=$OBJ/pidfile trap fatal 3 2 -if ssh_version 1; then - PROTO="2,1" -else - PROTO="2" -fi - # create server config cat << EOF > $OBJ/sshd_config StrictModes no @@ -460,11 +450,8 @@ fi rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER -if ssh_version 1; then - SSH_KEYTYPES="rsa rsa1" -else - SSH_KEYTYPES="rsa ed25519" -fi +SSH_KEYTYPES="rsa ed25519" + trace "generate keys" for t in ${SSH_KEYTYPES}; do # generate user key diff --git a/regress/transfer.sh b/regress/transfer.sh index 36c14634ab9e..cf174a00678d 100644 --- a/regress/transfer.sh +++ b/regress/transfer.sh @@ -1,26 +1,23 @@ -# $OpenBSD: transfer.sh,v 1.3 2015/03/03 22:35:19 markus Exp $ +# $OpenBSD: transfer.sh,v 1.4 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="transfer data" -for p in ${SSH_PROTOCOLS}; do - verbose "$tid: proto $p" +rm -f ${COPY} +${SSH} -n -q -F $OBJ/ssh_proxy somehost cat ${DATA} > ${COPY} +if [ $? -ne 0 ]; then + fail "ssh cat $DATA failed" +fi +cmp ${DATA} ${COPY} || fail "corrupted copy" + +for s in 10 100 1k 32k 64k 128k 256k; do + trace "dd-size ${s}" rm -f ${COPY} - ${SSH} -n -q -$p -F $OBJ/ssh_proxy somehost cat ${DATA} > ${COPY} + dd if=$DATA obs=${s} 2> /dev/null | \ + ${SSH} -q -F $OBJ/ssh_proxy somehost "cat > ${COPY}" if [ $? -ne 0 ]; then fail "ssh cat $DATA failed" fi - cmp ${DATA} ${COPY} || fail "corrupted copy" - - for s in 10 100 1k 32k 64k 128k 256k; do - trace "proto $p dd-size ${s}" - rm -f ${COPY} - dd if=$DATA obs=${s} 2> /dev/null | \ - ${SSH} -q -$p -F $OBJ/ssh_proxy somehost "cat > ${COPY}" - if [ $? -ne 0 ]; then - fail "ssh cat $DATA failed" - fi - cmp $DATA ${COPY} || fail "corrupted copy" - done + cmp $DATA ${COPY} || fail "corrupted copy" done rm -f ${COPY} diff --git a/regress/try-ciphers.sh b/regress/try-ciphers.sh index 889a735d27dc..e04268ba35bf 100644 --- a/regress/try-ciphers.sh +++ b/regress/try-ciphers.sh @@ -1,4 +1,4 @@ -# $OpenBSD: try-ciphers.sh,v 1.25 2015/03/24 20:22:17 markus Exp $ +# $OpenBSD: try-ciphers.sh,v 1.26 2017/04/30 23:34:55 djm Exp $ # Placed in the Public Domain. tid="try ciphers" @@ -8,14 +8,14 @@ cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak for c in `${SSH} -Q cipher`; do n=0 for m in `${SSH} -Q mac`; do - trace "proto 2 cipher $c mac $m" - verbose "test $tid: proto 2 cipher $c mac $m" + trace "cipher $c mac $m" + verbose "test $tid: cipher $c mac $m" cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "Ciphers=$c" >> $OBJ/sshd_proxy echo "MACs=$m" >> $OBJ/sshd_proxy - ${SSH} -F $OBJ/ssh_proxy -2 -m $m -c $c somehost true + ${SSH} -F $OBJ/ssh_proxy -m $m -c $c somehost true if [ $? -ne 0 ]; then - fail "ssh -2 failed with mac $m cipher $c" + fail "ssh failed with mac $m cipher $c" fi # No point trying all MACs for AEAD ciphers since they # are ignored. @@ -26,17 +26,3 @@ for c in `${SSH} -Q cipher`; do done done -if ssh_version 1; then - ciphers="3des blowfish" -else - ciphers="" -fi -for c in $ciphers; do - trace "proto 1 cipher $c" - verbose "test $tid: proto 1 cipher $c" - ${SSH} -F $OBJ/ssh_proxy -1 -c $c somehost true - if [ $? -ne 0 ]; then - fail "ssh -1 failed with cipher $c" - fi -done - diff --git a/regress/unittests/Makefile.inc b/regress/unittests/Makefile.inc index 3d9eaba5c94e..36d1ff42c06e 100644 --- a/regress/unittests/Makefile.inc +++ b/regress/unittests/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.9 2016/11/01 13:43:27 tb Exp $ +# $OpenBSD: Makefile.inc,v 1.11 2017/04/30 23:33:48 djm Exp $ .include .include @@ -30,7 +30,7 @@ CDIAGFLAGS+= -Wswitch CDIAGFLAGS+= -Wtrigraphs CDIAGFLAGS+= -Wuninitialized CDIAGFLAGS+= -Wunused -.if ${COMPILER_VERSION} == "gcc4" +.if ${COMPILER_VERSION:L} != "gcc3" CDIAGFLAGS+= -Wpointer-sign CDIAGFLAGS+= -Wold-style-definition .endif diff --git a/regress/unittests/hostkeys/mktestdata.sh b/regress/unittests/hostkeys/mktestdata.sh index 36890ba11a76..5a46de990dca 100755 --- a/regress/unittests/hostkeys/mktestdata.sh +++ b/regress/unittests/hostkeys/mktestdata.sh @@ -1,11 +1,11 @@ #!/bin/sh -# $OpenBSD: mktestdata.sh,v 1.1 2015/02/16 22:18:34 djm Exp $ +# $OpenBSD: mktestdata.sh,v 1.2 2017/04/30 23:33:48 djm Exp $ set -ex cd testdata -rm -f rsa1* rsa* dsa* ecdsa* ed25519* +rm -f rsa* dsa* ecdsa* ed25519* rm -f known_hosts* gen_all() { @@ -13,13 +13,12 @@ gen_all() { _ecdsa_bits=256 test "x$_n" = "x1" && _ecdsa_bits=384 test "x$_n" = "x2" && _ecdsa_bits=521 - ssh-keygen -qt rsa1 -b 1024 -C "RSA1 #$_n" -N "" -f rsa1_$_n ssh-keygen -qt rsa -b 1024 -C "RSA #$_n" -N "" -f rsa_$_n ssh-keygen -qt dsa -b 1024 -C "DSA #$_n" -N "" -f dsa_$_n ssh-keygen -qt ecdsa -b $_ecdsa_bits -C "ECDSA #$_n" -N "" -f ecdsa_$_n ssh-keygen -qt ed25519 -C "ED25519 #$_n" -N "" -f ed25519_$_n # Don't need private keys - rm -f rsa1_$_n rsa_$_n dsa_$_n ecdsa_$_n ed25519_$_n + rm -f rsa_$_n dsa_$_n ecdsa_$_n ed25519_$_n } hentries() { @@ -64,7 +63,6 @@ rm -f known_hosts_hash_frag.old echo echo "# Revoked and CA keys" - printf "@revoked sisyphus.example.com " ; cat rsa1_4.pub printf "@revoked sisyphus.example.com " ; cat ed25519_4.pub printf "@cert-authority prometheus.example.com " ; cat ecdsa_4.pub printf "@cert-authority *.example.com " ; cat dsa_4.pub @@ -72,19 +70,13 @@ rm -f known_hosts_hash_frag.old printf "\n" echo "# Some invalid lines" # Invalid marker - printf "@what sisyphus.example.com " ; cat rsa1_1.pub + printf "@what sisyphus.example.com " ; cat dsa_1.pub # Key missing echo "sisyphus.example.com " # Key blob missing echo "prometheus.example.com ssh-ed25519 " # Key blob truncated echo "sisyphus.example.com ssh-dsa AAAATgAAAAdz" - # RSA1 key truncated after key bits - echo "prometheus.example.com 1024 " - # RSA1 key truncated after exponent - echo "sisyphus.example.com 1024 65535 " - # RSA1 key incorrect key bits - printf "prometheus.example.com 1025 " ; cut -d' ' -f2- < rsa1_1.pub # Invalid type echo "sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg==" # Type mismatch with blob diff --git a/regress/unittests/hostkeys/test_iterate.c b/regress/unittests/hostkeys/test_iterate.c index 2eaaf063ac41..751825ddae9e 100644 --- a/regress/unittests/hostkeys/test_iterate.c +++ b/regress/unittests/hostkeys/test_iterate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_iterate.c,v 1.4 2015/03/31 22:59:01 djm Exp $ */ +/* $OpenBSD: test_iterate.c,v 1.5 2017/04/30 23:33:48 djm Exp $ */ /* * Regress test for hostfile.h hostkeys_foreach() * @@ -90,14 +90,6 @@ check(struct hostkey_foreach_line *l, void *_ctx) expected_keytype = (parse_key || expected->no_parse_keytype < 0) ? expected->l.keytype : expected->no_parse_keytype; -#ifndef WITH_SSH1 - if (parse_key && (expected->l.keytype == KEY_RSA1 || - expected->no_parse_keytype == KEY_RSA1)) { - expected_status = HKF_STATUS_INVALID; - expected_keytype = KEY_UNSPEC; - parse_key = 0; - } -#endif #ifndef OPENSSL_HAS_ECC if (expected->l.keytype == KEY_ECDSA || expected->no_parse_keytype == KEY_ECDSA) { @@ -150,10 +142,6 @@ prepare_expected(struct expected *expected, size_t n) for (i = 0; i < n; i++) { if (expected[i].key_file == NULL) continue; -#ifndef WITH_SSH1 - if (expected[i].l.keytype == KEY_RSA1) - continue; -#endif #ifndef OPENSSL_HAS_ECC if (expected[i].l.keytype == KEY_ECDSA) continue; @@ -217,22 +205,9 @@ struct expected expected_full[] = { NULL, /* filled at runtime */ "ED25519 #1", } }, - { "rsa1_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { - NULL, - 5, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - "sisyphus.example.com", - NULL, - KEY_RSA1, - NULL, /* filled at runtime */ - "RSA1 #1", - } }, { "rsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, - 6, + 5, HKF_STATUS_OK, 0, NULL, @@ -245,7 +220,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 7, + 6, HKF_STATUS_COMMENT, 0, "", @@ -258,7 +233,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 8, + 7, HKF_STATUS_COMMENT, 0, "# Plain host keys, hostnames + addresses", @@ -271,7 +246,7 @@ struct expected expected_full[] = { } }, { "dsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 9, + 8, HKF_STATUS_OK, 0, NULL, @@ -284,7 +259,7 @@ struct expected expected_full[] = { } }, { "ecdsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 10, + 9, HKF_STATUS_OK, 0, NULL, @@ -297,7 +272,7 @@ struct expected expected_full[] = { } }, { "ed25519_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 11, + 10, HKF_STATUS_OK, 0, NULL, @@ -308,22 +283,9 @@ struct expected expected_full[] = { NULL, /* filled at runtime */ "ED25519 #2", } }, - { "rsa1_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { - NULL, - 12, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - "prometheus.example.com,192.0.2.1,2001:db8::1", - NULL, - KEY_RSA1, - NULL, /* filled at runtime */ - "RSA1 #2", - } }, { "rsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 13, + 11, HKF_STATUS_OK, 0, NULL, @@ -336,7 +298,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 14, + 12, HKF_STATUS_COMMENT, 0, "", @@ -349,7 +311,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 15, + 13, HKF_STATUS_COMMENT, 0, "# Some hosts with wildcard names / IPs", @@ -362,7 +324,7 @@ struct expected expected_full[] = { } }, { "dsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 16, + 14, HKF_STATUS_OK, 0, NULL, @@ -375,7 +337,7 @@ struct expected expected_full[] = { } }, { "ecdsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 17, + 15, HKF_STATUS_OK, 0, NULL, @@ -388,7 +350,7 @@ struct expected expected_full[] = { } }, { "ed25519_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 18, + 16, HKF_STATUS_OK, 0, NULL, @@ -399,22 +361,9 @@ struct expected expected_full[] = { NULL, /* filled at runtime */ "ED25519 #3", } }, - { "rsa1_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { - NULL, - 19, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - "*.example.com,192.0.2.*,2001:*", - NULL, - KEY_RSA1, - NULL, /* filled at runtime */ - "RSA1 #3", - } }, { "rsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 20, + 17, HKF_STATUS_OK, 0, NULL, @@ -427,7 +376,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 21, + 18, HKF_STATUS_COMMENT, 0, "", @@ -440,7 +389,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 22, + 19, HKF_STATUS_COMMENT, 0, "# Hashed hostname and address entries", @@ -453,7 +402,7 @@ struct expected expected_full[] = { } }, { "dsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, - 23, + 20, HKF_STATUS_OK, 0, NULL, @@ -466,7 +415,7 @@ struct expected expected_full[] = { } }, { "ecdsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, - 24, + 21, HKF_STATUS_OK, 0, NULL, @@ -479,7 +428,7 @@ struct expected expected_full[] = { } }, { "ed25519_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, - 25, + 22, HKF_STATUS_OK, 0, NULL, @@ -490,22 +439,9 @@ struct expected expected_full[] = { NULL, /* filled at runtime */ "ED25519 #5", } }, - { "rsa1_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { - NULL, - 26, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - NULL, - NULL, - KEY_RSA1, - NULL, /* filled at runtime */ - "RSA1 #5", - } }, { "rsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, - 27, + 23, HKF_STATUS_OK, 0, NULL, @@ -518,7 +454,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 28, + 24, HKF_STATUS_COMMENT, 0, "", @@ -536,7 +472,7 @@ struct expected expected_full[] = { */ { "dsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { NULL, - 29, + 25, HKF_STATUS_OK, 0, NULL, @@ -549,7 +485,7 @@ struct expected expected_full[] = { } }, { "dsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, - 30, + 26, HKF_STATUS_OK, 0, NULL, @@ -562,7 +498,7 @@ struct expected expected_full[] = { } }, { "dsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, - 31, + 27, HKF_STATUS_OK, 0, NULL, @@ -575,7 +511,7 @@ struct expected expected_full[] = { } }, { "ecdsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { NULL, - 32, + 28, HKF_STATUS_OK, 0, NULL, @@ -588,7 +524,7 @@ struct expected expected_full[] = { } }, { "ecdsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, - 33, + 29, HKF_STATUS_OK, 0, NULL, @@ -601,7 +537,7 @@ struct expected expected_full[] = { } }, { "ecdsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, - 34, + 30, HKF_STATUS_OK, 0, NULL, @@ -614,7 +550,7 @@ struct expected expected_full[] = { } }, { "ed25519_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { NULL, - 35, + 31, HKF_STATUS_OK, 0, NULL, @@ -627,7 +563,7 @@ struct expected expected_full[] = { } }, { "ed25519_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, - 36, + 32, HKF_STATUS_OK, 0, NULL, @@ -640,7 +576,7 @@ struct expected expected_full[] = { } }, { "ed25519_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, - 37, + 33, HKF_STATUS_OK, 0, NULL, @@ -651,48 +587,9 @@ struct expected expected_full[] = { NULL, /* filled at runtime */ "ED25519 #6", } }, - { "rsa1_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { - NULL, - 38, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - NULL, - NULL, - KEY_RSA1, - NULL, /* filled at runtime */ - "RSA1 #6", - } }, - { "rsa1_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { - NULL, - 39, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - NULL, - NULL, - KEY_RSA1, - NULL, /* filled at runtime */ - "RSA1 #6", - } }, - { "rsa1_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { - NULL, - 40, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - NULL, - NULL, - KEY_RSA1, - NULL, /* filled at runtime */ - "RSA1 #6", - } }, { "rsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { NULL, - 41, + 34, HKF_STATUS_OK, 0, NULL, @@ -705,7 +602,7 @@ struct expected expected_full[] = { } }, { "rsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, - 42, + 35, HKF_STATUS_OK, 0, NULL, @@ -718,7 +615,7 @@ struct expected expected_full[] = { } }, { "rsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, - 43, + 36, HKF_STATUS_OK, 0, NULL, @@ -731,7 +628,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 44, + 37, HKF_STATUS_COMMENT, 0, "", @@ -744,7 +641,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 45, + 38, HKF_STATUS_COMMENT, 0, "", @@ -757,7 +654,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 46, + 39, HKF_STATUS_COMMENT, 0, "# Revoked and CA keys", @@ -768,22 +665,9 @@ struct expected expected_full[] = { NULL, NULL, } }, - { "rsa1_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { - NULL, - 47, - HKF_STATUS_OK, - 0, - NULL, - MRK_REVOKE, - "sisyphus.example.com", - NULL, - KEY_RSA1, - NULL, /* filled at runtime */ - "RSA1 #4", - } }, { "ed25519_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, - 48, + 40, HKF_STATUS_OK, 0, NULL, @@ -796,7 +680,7 @@ struct expected expected_full[] = { } }, { "ecdsa_4.pub" , -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, { NULL, - 49, + 41, HKF_STATUS_OK, 0, NULL, @@ -809,7 +693,7 @@ struct expected expected_full[] = { } }, { "dsa_4.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, 0, 0, -1, { NULL, - 50, + 42, HKF_STATUS_OK, 0, NULL, @@ -822,7 +706,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 51, + 43, HKF_STATUS_COMMENT, 0, "", @@ -835,7 +719,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 52, + 44, HKF_STATUS_COMMENT, 0, "# Some invalid lines", @@ -848,7 +732,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 53, + 45, HKF_STATUS_INVALID, 0, NULL, @@ -861,7 +745,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, - 54, + 46, HKF_STATUS_INVALID, 0, NULL, @@ -874,7 +758,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, { NULL, - 55, + 47, HKF_STATUS_INVALID, 0, NULL, @@ -887,7 +771,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, - 56, + 48, HKF_STATUS_INVALID, /* Would be ok if key not parsed */ 0, NULL, @@ -898,48 +782,9 @@ struct expected expected_full[] = { NULL, NULL, } }, - { NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, { - NULL, - 57, - HKF_STATUS_INVALID, /* Would be ok if key not parsed */ - 0, - NULL, - MRK_NONE, - "prometheus.example.com", - NULL, - KEY_UNSPEC, - NULL, - NULL, - } }, - { NULL, HKF_STATUS_OK, KEY_RSA1, 0, HKF_MATCH_HOST, 0, 0, -1, { - NULL, - 58, - HKF_STATUS_INVALID, /* Would be ok if key not parsed */ - 0, - NULL, - MRK_NONE, - "sisyphus.example.com", - NULL, - KEY_UNSPEC, - NULL, - NULL, - } }, - { NULL, HKF_STATUS_OK, KEY_RSA1, HKF_MATCH_HOST, 0, 0, 0, -1, { - NULL, - 59, - HKF_STATUS_INVALID, /* Would be ok if key not parsed */ - 0, - NULL, - MRK_NONE, - "prometheus.example.com", - NULL, - KEY_UNSPEC, - NULL, /* filled at runtime */ - NULL, - } }, { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, - 60, + 49, HKF_STATUS_INVALID, 0, NULL, @@ -952,7 +797,7 @@ struct expected expected_full[] = { } }, { NULL, HKF_STATUS_OK, KEY_RSA, HKF_MATCH_HOST, 0, 0, 0, -1, { NULL, - 61, + 50, HKF_STATUS_INVALID, /* Would be ok if key not parsed */ 0, NULL, diff --git a/regress/unittests/hostkeys/testdata/known_hosts b/regress/unittests/hostkeys/testdata/known_hosts index 3740f674b48b..4446f45dffe8 100644 --- a/regress/unittests/hostkeys/testdata/known_hosts +++ b/regress/unittests/hostkeys/testdata/known_hosts @@ -2,60 +2,49 @@ sisyphus.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1 sisyphus.example.com ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF6yQEtD9yBw9gmDRf477WBBzvWhAa0ioBI3nbA4emKykj0RbuQd5C4XdQAEOZGzE7v//FcCjwB2wi+JH5eKkxCtN6CjohDASZ1huoIV2UVyYIicZJEEOg1IWjjphvaxtw== ECDSA #1 sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9ks7jkua5YWIwByRnnnc6UPJQWI75O0e/UJdPYU1JI ED25519 #1 -sisyphus.example.com 1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1 sisyphus.example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDg4hB4vAZHJ0PVRiJajOv/GlytFWNpv5/9xgB9+5BIbvp8LOrFZ5D9K0Gsmwpd4G4rfaAz8j896DhMArg0vtkilIPPGt/6VzWMERgvaIQPJ/IE99X3+fjcAG56oAWwy29JX10lQMzBPU6XJIaN/zqpkb6qUBiAHBdLpxrFBBU0/w== RSA #1 # Plain host keys, hostnames + addresses prometheus.example.com,192.0.2.1,2001:db8::1 ssh-dss AAAAB3NzaC1kc3MAAACBAI38Hy/61/O5Bp6yUG8J5XQCeNjRS0xvjlCdzKLyXCueMa+L+X2L/u9PWUsy5SVbTjGgpB8sF6UkCNsV+va7S8zCCHas2MZ7GPlxP6GZBkRPTIFR0N/Pu7wfBzDQz0t0iL4VmxBfTBQv/SxkGWZg+yHihIQP9fwdSAwD/7aVh6ItAAAAFQDSyihIUlINlswM0PJ8wXSti3yIMwAAAIB+oqzaB6ozqs8YxpN5oQOBa/9HEBQEsp8RSIlQmVubXRNgktp42n+Ii1waU9UUk8DX5ahhIeR6B7ojWkqmDAji4SKpoHf4kmr6HvYo85ZSTSx0W4YK/gJHSpDJwhlT52tAfb1JCbWSObjl09B4STv7KedCHcR5oXQvvrV+XoKOSAAAAIAue/EXrs2INw1RfaKNHC0oqOMxmRitv0BFMuNVPo1VDj39CE5kA7AHjwvS1TNeaHtK5Hhgeb6vsmLmNPTOc8xCob0ilyQbt9O0GbONeF2Ge7D2UJyULA/hxql+tCYFIC6yUrmo35fF9XiNisXLoaflk9fjp7ROWWVwnki/jstaQw== DSA #2 prometheus.example.com,192.0.2.1,2001:db8::1 ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB8qVcXwgBM92NCmReQlPrZAoui4Bz/mW0VUBFOpHXXW1n+15b/Y7Pc6UBd/ITTZmaBciXY+PWaSBGdwc5GdqGdLgFyJ/QAGrFMPNpVutm/82gNQzlxpNwjbMcKyiZEXzSgnjS6DzMQ0WuSMdzIBXq8OW/Kafxg4ZkU6YqALUXxlQMZuQ== ECDSA #2 prometheus.example.com,192.0.2.1,2001:db8::1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBp6PVW0z2o9C4Ukv/JOgmK7QMFe1pD1s3ADFF7IQob ED25519 #2 -prometheus.example.com,192.0.2.1,2001:db8::1 1024 65537 135970715082947442639683969597180728933388298633245835186618852623800675939308729462220235058285909679252157995530180587329132927339620517781785310829060832352381015614725360278571924286986474946772141568893116432268565829418506866604294073334978275702221949783314402806080929601995102334442541344606109853641 RSA1 #2 prometheus.example.com,192.0.2.1,2001:db8::1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDmbUhNabB5AmBDX6GNHZ3lbn7pRxqfpW+f53QqNGlK0sLV+0gkMIrOfUp1kdE2ZLE6tfzdicatj/RlH6/wuo4yyYb+Pyx3G0vxdmAIiA4aANq38XweDucBC0TZkRWVHK+Gs5V/uV0z7N0axJvkkJujMLvST3CRiiWwlficBc6yVQ== RSA #2 # Some hosts with wildcard names / IPs *.example.com,192.0.2.*,2001:* ssh-dss AAAAB3NzaC1kc3MAAACBAI6lz2Ip9bzE7TGuDD4SjO9S4Ac90gq0h6ai1O06eI8t/Ot2uJ5Jk2QyVr2jvIZHDl/5bwBx7+5oyjlwRoUrAPPD814wf5tU2tSnmdu1Wbf0cBswif5q0r4tevzmopp/AtgH11QHo3u0/pfyJd10qBDLV2FaYSKMmZvyPfZJ0s9pAAAAFQD5Eqjl6Rx2qVePodD9OwAPT0bU6wAAAIAfnDm6csZF0sFaJR3NIJvaYgSGr8s7cqlsk2gLltB/1wOOO2yX+NeEC+B0H93hlMfaUsPa08bwgmYxnavSMqEBpmtPceefJiEd68zwYqXd38f88wyWZ9Z5iwaI/6OVZPHzCbDxOa4ewVTevRNYUKP1xUTZNT8/gSMfZLYPk4T2AQAAAIAUKroozRMyV+3V/rxt0gFnNxRXBKk+9cl3vgsQ7ktkI9cYg7V1T2K0XF21AVMK9gODszy6PBJjV6ruXBV6TRiqIbQauivp3bHHKYsG6wiJNqwdbVwIjfvv8nn1qFoZQLXG3sdONr9NwN8KzrX89OV0BlR2dVM5qqp+YxOXymP9yg== DSA #3 *.example.com,192.0.2.*,2001:* ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIb3BhJZk+vUQPg5TQc1koIzuGqloCq7wjr9LjlhG24IBeiFHLsdWw74HDlH4DrOmlxToVYk2lTdnjARleRByjk= ECDSA #3 *.example.com,192.0.2.*,2001:* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlYfExtYZAPqYvYdrlpGlSWhh/XNHcH3v3c2JzsVNbB ED25519 #3 -*.example.com,192.0.2.*,2001:* 1024 65537 125895605498029643697051635076028105429632810811904702876152645261610759866299221305725069141163240694267669117205342283569102183636228981857946763978553664895308762890072813014496700601576921921752482059207749978374872713540759920335553799711267170948655579130584031555334229966603000896364091459595522912269 RSA1 #3 *.example.com,192.0.2.*,2001:* ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDX8F93W3SH4ZSus4XUQ2cw9dqcuyUETTlKEeGv3zlknV3YCoe2Mp04naDhiuwj8sOsytrZSESzLY1ZEyzrjxE6ZFVv8NKgck/AbRjcwlRFOcx9oKUxOrXRa0IoXlTq0kyjKCJfaHBKnGitZThknCPTbVmpATkm5xx6J0WEDozfoQ== RSA #3 # Hashed hostname and address entries -|1|6FWxoqTCAfm8sZ7T/q73OmxCFGM=|S4eQmusok4cbyDzzGEFGIAthDbw= ssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5 -|1|hTrfD0CuuB9ZbOa1CHFYvIk/gKE=|tPmW50t7flncm1UyM+DR97ubDNU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5 -|1|fOGqe75X5ZpTz4c7DitP4E8/y30=|Lmcch2fh54bUYoV//S2VqDFVeiY= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5 -|1|0RVzLjY3lwE3MRweguaAXaCCWk8=|DbcIgJQcRZJMYI6NYDOM6oJycPk= 1024 65537 127931411493401587586867047972295564331543694182352197506125410692673654572057908999642645524647232712160516076508316152810117209181150078352725299319149726341058893406440426414316276977768958023952319602422835879783057966985348561111880658922724668687074412548487722084792283453716871417610020757212399252171 RSA1 #5 -|1|4q79XnHpKBNQhyMLAqbPPDN+JKo=|k1Wvjjb52zDdrXWM801+wX5oH8U= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5 +|1|z3xOIdT5ue3Vuf3MzT67kaioqjw=|GZhhe5uwDOBQrC9N4cCjpbLpSn4= ssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5 +|1|B7t/AYabn8zgwU47Cb4A/Nqt3eI=|arQPZyRphkzisr7w6wwikvhaOyE= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5 +|1|JR81WxEocTP5d7goIRkl8fHBbno=|l6sj6FOsoXxgEZMzn/BnOfPKN68= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5 +|1|W7x4zY6KtTZJgsopyOusJqvVPag=|QauLt7hKezBZFZi2i4Xopho7Nsk= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5 -|1|0M6PIx6THA3ipIOvTl3fcgn2z+A=|bwEJAOwJz+Sm7orFdgj170mD/zY= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 -|1|a6WGHcL+9gX3e96tMlgDSDJwtSg=|5Dqlb/yqNEf7jgfllrp/ygLmRV8= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 -|1|OeCpi7Pn5Q6c8la4fPf9G8YctT8=|sC6D7lDXTafIpokZJ1+1xWg2R6Q= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 -|1|BHESVyiJ7G2NN0lxrw7vT109jmk=|TKof+015J77bXqibsh0N1Lp0MKk= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 -|1|wY53mZNASDJ5/P3JYCJ4FUNa6WQ=|v8p0MfV5lqlZB2J0yLxl/gsWVQo= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 -|1|horeoyFPwfKhyFN+zJZ5LCfOo/I=|2ofvp0tNwCbKsV8FuiFA4gQG2Z8= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 -|1|Aw4fXumZfx6jEIJuDGIyeEMd81A=|5FdLtdm2JeKNsS8IQeQlGYIadOE= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 -|1|+dGUNpv6GblrDd5fgHLlOWpSbEo=|He/pQ1yJjtiCyTNWpGwjBD4sZFI= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 -|1|E/PACGl8m1T7QnPedOoooozstP0=|w6DQAFT8yZgj0Hlkz5R1TppYHCA= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 -|1|SaoyMStgxpYfwedSXBAghi8Zo0s=|Gz78k69GaE6iViV3OOvbStKqyTA= 1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6 -|1|8qfGeiT5WTCzWYbXPQ+lsLg7km4=|1sIBwiSUr8IGkvrUGm3/9QYurmA= 1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6 -|1|87M1OtyHg1BZiDY3rT6lYsZFnAU=|eddAQVcMNbn2OB87XWXFQnYo6R4= 1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6 -|1|60w3wFfC0XWI+rRmRlxIRhh8lwE=|yMhsGrzBJKiesAdSQ/PVgkCrDKk= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 -|1|5gdEMmLUJC7grqWhRJPy2OTaSyE=|/XTfmLMa/B8npcVCGFRdaHl+d/0= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 -|1|6FGCWUr42GHdMB/eifnHNCuwgdk=|ONJvYZ/ANmi59R5HrOhLPmvYENM= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 +|1|mxnU8luzqWLvfVi5qBm5xVIyCRM=|9Epopft7LBd80Bf6RmWPIpwa8yU= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 +|1|klvLmvh2vCpkNMDEjVvrE8SJWTg=|e/dqEEBLnbgqmwEesl4cDRu/7TM= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 +|1|wsk3ddB3UjuxEsoeNCeZjZ6NvZs=|O3O/q2Z/u7DrxoTiIq6kzCevQT0= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 +|1|B8epmkLSni+vGZDijr/EwxeR2k4=|7ct8yzNOVJhKm3ZD2w0XIT7df8E= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 +|1|JojD885UhYhbCu571rgyM/5PpYU=|BJaU2aE1FebQZy3B5tzTDRWFRG0= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 +|1|5t7UDHDybVrDZVQPCpwdnr6nk4k=|EqJ73W/veIL3H2x+YWHcJxI5ETA= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 +|1|OCcBfGc/b9+ip+W6Gp+3ftdluO4=|VbrKUdzOOtIBOOmEE+jlK4SD3Xc= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 +|1|9fLN0YdP+BJ25lKuKvYuOdUo93w=|vZyr0rOiX01hv5XbghhHMW+Zb3U= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 +|1|nc9RoaaQ0s5jdPxwlUmluGHU3uk=|un6OsJajokKQ3MgyS9mfDNeyP6U= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6 +|1|rsHB6juT9q6GOY91qOeOwL6TSJE=|ps/vXF9Izuues5PbOn887Gw/2Dg= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 +|1|BsckdLH2aRyWQooRmv+Yo3t4dKg=|Lf3tJc5Iyx0KxNwAG89FsImsfEE= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 +|1|plqkBA4hq7UATyd5+/Xl+zL7ghw=|stacofaUed46666mfqxp9gJFjt4= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6 # Revoked and CA keys -@revoked sisyphus.example.com 1024 65537 174143366122697048196335388217056770310345753698079464367148030836533360510864881734142526411160017107552815906024399248049666856133771656680462456979369587903909343046704480897527203474513676654933090991684252819423129896444427656841613263783484827101210734799449281639493127615902427443211183258155381810593 RSA1 #4 @revoked sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFP8L9REfN/iYy1KIRtFqSCn3V2+vOCpoZYENFGLdOF ED25519 #4 @cert-authority prometheus.example.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHZd0OXHIWwK3xnjAdMZ1tojxWycdu38pORO/UX5cqsKMgGCKQVBWWO3TFk1ePkGIE9VMWT1hCGqWRRwYlH+dSE= ECDSA #4 @cert-authority *.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAKvjnFHm0VvMr5h2Zu3nURsxQKGoxm+DCzYDxRYcilK07Cm5c4XTrFbA2X86+9sGs++W7QRMcTJUYIg0a+UtIMtAjwORd6ZPXM2K5dBW+gh1oHyvKi767tWX7I2c+1ZPJDY95mUUfZQUEfdy9eGDSBmw/pSsveQ1ur6XNUh/MtP/AAAAFQDHnXk/9jBJAdce1pHtLWnbdPSGdQAAAIEAm2OLy8tZBfiEO3c3X1yyB/GTcDwrQCqRMDkhnsmrliec3dWkOfNTzu+MrdvF8ymTWLEqPpbMheYtvNyZ3TF0HO5W7aVBpdGZbOdOAIfB+6skqGbI8A5Up1d7dak/bSsqL2r5NjwbDOdq+1hBzzvbl/qjh+sQarV2zHrpKoQaV28AAACANtkBVedBbqIAdphCrN/LbUi9WlyuF9UZz+tlpVLYrj8GJVwnplV2tvOmUw6yP5/pzCimTsao8dpL5PWxm7fKxLWVxA+lEsA4WeC885CiZn8xhdaJOCN+NyJ2bqkz+4VPI7oDGBm0aFwUqJn+M1PiSgvI50XdF2dBsFRTRNY0wzA= DSA #4 # Some invalid lines -@what sisyphus.example.com 1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1 +@what sisyphus.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1 sisyphus.example.com prometheus.example.com ssh-ed25519 sisyphus.example.com ssh-dsa AAAATgAAAAdz -prometheus.example.com 1024 -sisyphus.example.com 1024 65535 -prometheus.example.com 1025 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1 sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg== prometheus.example.com ssh-rsa AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg== diff --git a/regress/unittests/sshkey/mktestdata.sh b/regress/unittests/sshkey/mktestdata.sh index e11100145d49..8047bc62ffd8 100755 --- a/regress/unittests/sshkey/mktestdata.sh +++ b/regress/unittests/sshkey/mktestdata.sh @@ -1,25 +1,8 @@ #!/bin/sh -# $OpenBSD: mktestdata.sh,v 1.5 2015/07/07 14:53:30 markus Exp $ +# $OpenBSD: mktestdata.sh,v 1.6 2017/04/30 23:33:48 djm Exp $ PW=mekmitasdigoat -rsa1_params() { - _in="$1" - _outbase="$2" - set -e - ssh-keygen -f $_in -e -m pkcs8 | \ - openssl rsa -noout -text -pubin | \ - awk '/^Modulus:$/,/^Exponent:/' | \ - grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.n - # XXX need conversion support in ssh-keygen for the other params - for x in n ; do - echo "" >> ${_outbase}.$x - echo ============ ${_outbase}.$x - cat ${_outbase}.$x - echo ============ - done -} - rsa_params() { _in="$1" _outbase="$2" @@ -87,20 +70,18 @@ set -ex cd testdata -rm -f rsa1_1 rsa_1 dsa_1 ecdsa_1 ed25519_1 -rm -f rsa1_2 rsa_2 dsa_2 ecdsa_2 ed25519_2 +rm -f rsa_1 dsa_1 ecdsa_1 ed25519_1 +rm -f rsa_2 dsa_2 ecdsa_2 ed25519_2 rm -f rsa_n dsa_n ecdsa_n # new-format keys -rm -f rsa1_1_pw rsa_1_pw dsa_1_pw ecdsa_1_pw ed25519_1_pw +rm -f rsa_1_pw dsa_1_pw ecdsa_1_pw ed25519_1_pw rm -f rsa_n_pw dsa_n_pw ecdsa_n_pw rm -f pw *.pub *.bn.* *.param.* *.fp *.fp.bb -ssh-keygen -t rsa1 -b 1024 -C "RSA1 test key #1" -N "" -f rsa1_1 ssh-keygen -t rsa -b 1024 -C "RSA test key #1" -N "" -f rsa_1 ssh-keygen -t dsa -b 1024 -C "DSA test key #1" -N "" -f dsa_1 ssh-keygen -t ecdsa -b 256 -C "ECDSA test key #1" -N "" -f ecdsa_1 ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_1 -ssh-keygen -t rsa1 -b 2048 -C "RSA1 test key #2" -N "" -f rsa1_2 ssh-keygen -t rsa -b 2048 -C "RSA test key #2" -N "" -f rsa_2 ssh-keygen -t dsa -b 1024 -C "DSA test key #2" -N "" -f dsa_2 ssh-keygen -t ecdsa -b 521 -C "ECDSA test key #2" -N "" -f ecdsa_2 @@ -110,7 +91,6 @@ cp rsa_1 rsa_n cp dsa_1 dsa_n cp ecdsa_1 ecdsa_n -cp rsa1_1 rsa1_1_pw cp rsa_1 rsa_1_pw cp dsa_1 dsa_1_pw cp ecdsa_1 ecdsa_1_pw @@ -119,7 +99,6 @@ cp rsa_1 rsa_n_pw cp dsa_1 dsa_n_pw cp ecdsa_1 ecdsa_n_pw -ssh-keygen -pf rsa1_1_pw -N "$PW" ssh-keygen -pf rsa_1_pw -N "$PW" ssh-keygen -pf dsa_1_pw -N "$PW" ssh-keygen -pf ecdsa_1_pw -N "$PW" @@ -128,8 +107,6 @@ ssh-keygen -opf rsa_n_pw -N "$PW" ssh-keygen -opf dsa_n_pw -N "$PW" ssh-keygen -opf ecdsa_n_pw -N "$PW" -rsa1_params rsa1_1 rsa1_1.param -rsa1_params rsa1_2 rsa1_2.param rsa_params rsa_1 rsa_1.param rsa_params rsa_2 rsa_2.param dsa_params dsa_1 dsa_1.param @@ -160,12 +137,10 @@ ssh-keygen -s ecdsa_1 -I julius -n host1,host2 -h \ ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ -V 19990101:20110101 -z 8 ed25519_1.pub -ssh-keygen -lf rsa1_1 | awk '{print $2}' > rsa1_1.fp ssh-keygen -lf rsa_1 | awk '{print $2}' > rsa_1.fp ssh-keygen -lf dsa_1 | awk '{print $2}' > dsa_1.fp ssh-keygen -lf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp ssh-keygen -lf ed25519_1 | awk '{print $2}' > ed25519_1.fp -ssh-keygen -lf rsa1_2 | awk '{print $2}' > rsa1_2.fp ssh-keygen -lf rsa_2 | awk '{print $2}' > rsa_2.fp ssh-keygen -lf dsa_2 | awk '{print $2}' > dsa_2.fp ssh-keygen -lf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp @@ -176,12 +151,10 @@ ssh-keygen -lf ecdsa_1-cert.pub | awk '{print $2}' > ecdsa_1-cert.fp ssh-keygen -lf ed25519_1-cert.pub | awk '{print $2}' > ed25519_1-cert.fp ssh-keygen -lf rsa_1-cert.pub | awk '{print $2}' > rsa_1-cert.fp -ssh-keygen -Bf rsa1_1 | awk '{print $2}' > rsa1_1.fp.bb ssh-keygen -Bf rsa_1 | awk '{print $2}' > rsa_1.fp.bb ssh-keygen -Bf dsa_1 | awk '{print $2}' > dsa_1.fp.bb ssh-keygen -Bf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp.bb ssh-keygen -Bf ed25519_1 | awk '{print $2}' > ed25519_1.fp.bb -ssh-keygen -Bf rsa1_2 | awk '{print $2}' > rsa1_2.fp.bb ssh-keygen -Bf rsa_2 | awk '{print $2}' > rsa_2.fp.bb ssh-keygen -Bf dsa_2 | awk '{print $2}' > dsa_2.fp.bb ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c index 906491f2bc31..99b7e21c02d4 100644 --- a/regress/unittests/sshkey/test_file.c +++ b/regress/unittests/sshkey/test_file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_file.c,v 1.5 2015/10/06 01:20:59 djm Exp $ */ +/* $OpenBSD: test_file.c,v 1.6 2017/04/30 23:33:48 djm Exp $ */ /* * Regress test for sshkey.h key management API * @@ -51,55 +51,6 @@ sshkey_file_tests(void) pw = load_text_file("pw"); TEST_DONE(); -#ifdef WITH_SSH1 - TEST_START("parse RSA1 from private"); - buf = load_file("rsa1_1"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); - sshbuf_free(buf); - ASSERT_PTR_NE(k1, NULL); - a = load_bignum("rsa1_1.param.n"); - ASSERT_BIGNUM_EQ(k1->rsa->n, a); - BN_free(a); - TEST_DONE(); - - TEST_START("parse RSA1 from private w/ passphrase"); - buf = load_file("rsa1_1_pw"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, - (const char *)sshbuf_ptr(pw), &k2, NULL), 0); - sshbuf_free(buf); - ASSERT_PTR_NE(k2, NULL); - ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); - sshkey_free(k2); - TEST_DONE(); - - TEST_START("load RSA1 from public"); - ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa1_1.pub"), &k2, - NULL), 0); - ASSERT_PTR_NE(k2, NULL); - ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); - sshkey_free(k2); - TEST_DONE(); - - TEST_START("RSA1 key hex fingerprint"); - buf = load_text_file("rsa1_1.fp"); - cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); - ASSERT_PTR_NE(cp, NULL); - ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); - sshbuf_free(buf); - free(cp); - TEST_DONE(); - - TEST_START("RSA1 key bubblebabble fingerprint"); - buf = load_text_file("rsa1_1.fp.bb"); - cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); - ASSERT_PTR_NE(cp, NULL); - ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); - sshbuf_free(buf); - free(cp); - TEST_DONE(); - - sshkey_free(k1); -#endif TEST_START("parse RSA from private"); buf = load_file("rsa_1"); diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c index 1f414e0acaa2..6706045d5060 100644 --- a/regress/unittests/sshkey/test_fuzz.c +++ b/regress/unittests/sshkey/test_fuzz.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_fuzz.c,v 1.6 2015/12/07 02:20:46 djm Exp $ */ +/* $OpenBSD: test_fuzz.c,v 1.7 2017/04/30 23:33:48 djm Exp $ */ /* * Fuzz tests for key parsing * @@ -104,49 +104,6 @@ sshkey_fuzz_tests(void) struct fuzz *fuzz; int r; -#ifdef WITH_SSH1 - TEST_START("fuzz RSA1 private"); - buf = load_file("rsa1_1"); - fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | - FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, - sshbuf_mutable_ptr(buf), sshbuf_len(buf)); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); - sshkey_free(k1); - sshbuf_free(buf); - ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); - TEST_ONERROR(onerror, fuzz); - for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { - r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); - ASSERT_INT_EQ(r, 0); - if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) - sshkey_free(k1); - sshbuf_reset(fuzzed); - } - sshbuf_free(fuzzed); - fuzz_cleanup(fuzz); - TEST_DONE(); - - TEST_START("fuzz RSA1 public"); - buf = load_file("rsa1_1_pw"); - fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | - FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, - sshbuf_mutable_ptr(buf), sshbuf_len(buf)); - ASSERT_INT_EQ(sshkey_parse_public_rsa1_fileblob(buf, &k1, NULL), 0); - sshkey_free(k1); - sshbuf_free(buf); - ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); - TEST_ONERROR(onerror, fuzz); - for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { - r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); - ASSERT_INT_EQ(r, 0); - if (sshkey_parse_public_rsa1_fileblob(fuzzed, &k1, NULL) == 0) - sshkey_free(k1); - sshbuf_reset(fuzzed); - } - sshbuf_free(fuzzed); - fuzz_cleanup(fuzz); - TEST_DONE(); -#endif TEST_START("fuzz RSA private"); buf = load_file("rsa_1"); diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c index 1476dc2e305f..0a73322a34e5 100644 --- a/regress/unittests/sshkey/test_sshkey.c +++ b/regress/unittests/sshkey/test_sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_sshkey.c,v 1.10 2016/05/02 09:52:00 djm Exp $ */ +/* $OpenBSD: test_sshkey.c,v 1.12 2017/05/08 06:08:42 djm Exp $ */ /* * Regress test for sshkey.h key management API * @@ -193,16 +193,6 @@ sshkey_tests(void) sshkey_free(k1); TEST_DONE(); - TEST_START("new/free KEY_RSA1"); - k1 = sshkey_new(KEY_RSA1); - ASSERT_PTR_NE(k1, NULL); - ASSERT_PTR_NE(k1->rsa, NULL); - ASSERT_PTR_NE(k1->rsa->n, NULL); - ASSERT_PTR_NE(k1->rsa->e, NULL); - ASSERT_PTR_EQ(k1->rsa->p, NULL); - sshkey_free(k1); - TEST_DONE(); - TEST_START("new/free KEY_RSA"); k1 = sshkey_new(KEY_RSA); ASSERT_PTR_NE(k1, NULL); @@ -263,19 +253,19 @@ sshkey_tests(void) TEST_START("generate KEY_RSA too small modulus"); ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 128, &k1), - SSH_ERR_INVALID_ARGUMENT); + SSH_ERR_KEY_LENGTH); ASSERT_PTR_EQ(k1, NULL); TEST_DONE(); TEST_START("generate KEY_RSA too large modulus"); ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1 << 20, &k1), - SSH_ERR_INVALID_ARGUMENT); + SSH_ERR_KEY_LENGTH); ASSERT_PTR_EQ(k1, NULL); TEST_DONE(); TEST_START("generate KEY_DSA wrong bits"); ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 2048, &k1), - SSH_ERR_INVALID_ARGUMENT); + SSH_ERR_KEY_LENGTH); ASSERT_PTR_EQ(k1, NULL); sshkey_free(k1); TEST_DONE(); @@ -283,7 +273,7 @@ sshkey_tests(void) #ifdef OPENSSL_HAS_ECC TEST_START("generate KEY_ECDSA wrong bits"); ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 42, &k1), - SSH_ERR_INVALID_ARGUMENT); + SSH_ERR_KEY_LENGTH); ASSERT_PTR_EQ(k1, NULL); sshkey_free(k1); TEST_DONE(); @@ -291,7 +281,7 @@ sshkey_tests(void) TEST_START("generate KEY_RSA"); ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 767, &kr), - SSH_ERR_INVALID_ARGUMENT); + SSH_ERR_KEY_LENGTH); ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &kr), 0); ASSERT_PTR_NE(kr, NULL); ASSERT_PTR_NE(kr->rsa, NULL); diff --git a/regress/yes-head.sh b/regress/yes-head.sh index 1fc754211feb..fce2f6580344 100644 --- a/regress/yes-head.sh +++ b/regress/yes-head.sh @@ -3,13 +3,11 @@ tid="yes pipe head" -for p in ${SSH_PROTOCOLS}; do - lines=`${SSH} -$p -F $OBJ/ssh_proxy thishost 'sh -c "while true;do echo yes;done | _POSIX2_VERSION=199209 head -2000"' | (sleep 3 ; wc -l)` - if [ $? -ne 0 ]; then - fail "yes|head test failed" - lines = 0; - fi - if [ $lines -ne 2000 ]; then - fail "yes|head returns $lines lines instead of 2000" - fi -done +lines=`${SSH} -F $OBJ/ssh_proxy thishost 'sh -c "while true;do echo yes;done | _POSIX2_VERSION=199209 head -2000"' | (sleep 3 ; wc -l)` +if [ $? -ne 0 ]; then + fail "yes|head test failed" + lines = 0; +fi +if [ $lines -ne 2000 ]; then + fail "yes|head returns $lines lines instead of 2000" +fi diff --git a/rsa.c b/rsa.c deleted file mode 100644 index 5ecacef9030b..000000000000 --- a/rsa.c +++ /dev/null @@ -1,188 +0,0 @@ -/* $OpenBSD: rsa.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */ -/* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - * - * - * Copyright (c) 1999 Niels Provos. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Description of the RSA algorithm can be found e.g. from the following - * sources: - * - * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994. - * - * Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to - * Computer Security. Prentice-Hall, 1989. - * - * Man Young Rhee: Cryptography and Secure Data Communications. McGraw-Hill, - * 1994. - * - * R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications - * System and Method. US Patent 4,405,829, 1983. - * - * Hans Riesel: Prime Numbers and Computer Methods for Factorization. - * Birkhauser, 1994. - * - * The RSA Frequently Asked Questions document by RSA Data Security, - * Inc., 1995. - * - * RSA in 3 lines of perl by Adam Back , 1995, as - * included below: - * - * [gone - had to be deleted - what a pity] - */ - -#include "includes.h" - -#include - -#include -#include - -#include "rsa.h" -#include "log.h" -#include "ssherr.h" - -int -rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key) -{ - u_char *inbuf = NULL, *outbuf = NULL; - int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR; - - if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e)) - return SSH_ERR_INVALID_ARGUMENT; - - olen = BN_num_bytes(key->n); - if ((outbuf = malloc(olen)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - - ilen = BN_num_bytes(in); - if ((inbuf = malloc(ilen)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - BN_bn2bin(in, inbuf); - - if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key, - RSA_PKCS1_PADDING)) <= 0) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - - if (BN_bin2bn(outbuf, len, out) == NULL) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - r = 0; - - out: - if (outbuf != NULL) { - explicit_bzero(outbuf, olen); - free(outbuf); - } - if (inbuf != NULL) { - explicit_bzero(inbuf, ilen); - free(inbuf); - } - return r; -} - -int -rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) -{ - u_char *inbuf = NULL, *outbuf = NULL; - int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR; - - olen = BN_num_bytes(key->n); - if ((outbuf = malloc(olen)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - - ilen = BN_num_bytes(in); - if ((inbuf = malloc(ilen)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - BN_bn2bin(in, inbuf); - - if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key, - RSA_PKCS1_PADDING)) <= 0) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } else if (BN_bin2bn(outbuf, len, out) == NULL) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - r = 0; - out: - if (outbuf != NULL) { - explicit_bzero(outbuf, olen); - free(outbuf); - } - if (inbuf != NULL) { - explicit_bzero(inbuf, ilen); - free(inbuf); - } - return r; -} - -/* calculate p-1 and q-1 */ -int -rsa_generate_additional_parameters(RSA *rsa) -{ - BIGNUM *aux = NULL; - BN_CTX *ctx = NULL; - int r; - - if ((ctx = BN_CTX_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((aux = BN_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - - if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) || - (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) || - (BN_sub(aux, rsa->p, BN_value_one()) == 0) || - (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - r = 0; - out: - BN_clear_free(aux); - BN_CTX_free(ctx); - return r; -} - diff --git a/rsa.h b/rsa.h deleted file mode 100644 index c476707d53b8..000000000000 --- a/rsa.h +++ /dev/null @@ -1,26 +0,0 @@ -/* $OpenBSD: rsa.h,v 1.17 2014/06/24 01:13:21 djm Exp $ */ - -/* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * RSA key generation, encryption and decryption. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#ifndef RSA_H -#define RSA_H - -#include -#include - -int rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *); -int rsa_private_decrypt(BIGNUM *, BIGNUM *, RSA *); -int rsa_generate_additional_parameters(RSA *); - -#endif /* RSA_H */ diff --git a/sandbox-capsicum.c b/sandbox-capsicum.c index 655f0d21788c..e10bad7e83df 100644 --- a/sandbox-capsicum.c +++ b/sandbox-capsicum.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c index 3a1aedce72c2..ca75cc719b18 100644 --- a/sandbox-seccomp-filter.c +++ b/sandbox-seccomp-filter.c @@ -50,6 +50,9 @@ #include #include +#ifdef __s390__ +#include +#endif #include #include @@ -222,6 +225,7 @@ static const struct sock_filter preauth_insns[] = { #endif #ifdef __NR_socketcall SC_ALLOW_ARG(__NR_socketcall, 0, SYS_SHUTDOWN), + SC_DENY(__NR_socketcall, EACCES), #endif #if defined(__NR_ioctl) && defined(__s390__) /* Allow ioctls for ICA crypto card on s390 */ @@ -235,7 +239,7 @@ static const struct sock_filter preauth_insns[] = { * x86-64 syscall under some circumstances, e.g. * https://bugs.debian.org/849923 */ - SC_ALLOW(__NR_clock_gettime & ~__X32_SYSCALL_BIT); + SC_ALLOW(__NR_clock_gettime & ~__X32_SYSCALL_BIT), #endif /* Default deny */ diff --git a/sandbox-solaris.c b/sandbox-solaris.c index 343a01022850..56ddb9a9942a 100644 --- a/sandbox-solaris.c +++ b/sandbox-solaris.c @@ -61,6 +61,12 @@ ssh_sandbox_init(struct monitor *monitor) if (priv_delset(box->pset, PRIV_FILE_LINK_ANY) != 0 || #ifdef PRIV_NET_ACCESS priv_delset(box->pset, PRIV_NET_ACCESS) != 0 || +#endif +#ifdef PRIV_DAX_ACCESS + priv_delset(box->pset, PRIV_DAX_ACCESS) != 0 || +#endif +#ifdef PRIV_SYS_IB_INFO + priv_delset(box->pset, PRIV_SYS_IB_INFO) != 0 || #endif priv_delset(box->pset, PRIV_PROC_EXEC) != 0 || priv_delset(box->pset, PRIV_PROC_FORK) != 0 || diff --git a/scp.0 b/scp.0 index 46a084698bb9..0cb7726c7552 100644 --- a/scp.0 +++ b/scp.0 @@ -4,7 +4,7 @@ NAME scp M-bM-^@M-^S secure copy (remote file copy program) SYNOPSIS - scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file] + scp [-346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file] [-l limit] [-o ssh_option] [-P port] [-S program] [[user@]host1:]file1 ... [[user@]host2:]file2 @@ -22,10 +22,6 @@ DESCRIPTION The options are as follows: - -1 Forces scp to use protocol 1. - - -2 Forces scp to use protocol 2. - -3 Copies between two remote hosts are transferred through the local host. Without this option the data is copied directly between the two remote hosts. Note that this option disables the @@ -75,10 +71,8 @@ DESCRIPTION CertificateFile ChallengeResponseAuthentication CheckHostIP - Cipher Ciphers Compression - CompressionLevel ConnectionAttempts ConnectTimeout ControlMaster @@ -109,14 +103,11 @@ DESCRIPTION PKCS11Provider Port PreferredAuthentications - Protocol ProxyCommand ProxyJump PubkeyAcceptedKeyTypes PubkeyAuthentication RekeyLimit - RhostsRSAAuthentication - RSAAuthentication SendEnv ServerAliveInterval ServerAliveCountMax @@ -165,4 +156,4 @@ AUTHORS Timo Rinne Tatu Ylonen -OpenBSD 6.0 July 16, 2016 OpenBSD 6.0 +OpenBSD 6.2 May 3, 2017 OpenBSD 6.2 diff --git a/scp.1 b/scp.1 index 4ae8777534af..76ce33361273 100644 --- a/scp.1 +++ b/scp.1 @@ -8,9 +8,9 @@ .\" .\" Created: Sun May 7 00:14:37 1995 ylo .\" -.\" $OpenBSD: scp.1,v 1.71 2016/07/16 06:57:55 jmc Exp $ +.\" $OpenBSD: scp.1,v 1.74 2017/05/03 21:49:18 naddy Exp $ .\" -.Dd $Mdocdate: July 16 2016 $ +.Dd $Mdocdate: May 3 2017 $ .Dt SCP 1 .Os .Sh NAME @@ -19,7 +19,7 @@ .Sh SYNOPSIS .Nm scp .Bk -words -.Op Fl 12346BCpqrv +.Op Fl 346BCpqrv .Op Fl c Ar cipher .Op Fl F Ar ssh_config .Op Fl i Ar identity_file @@ -65,14 +65,6 @@ Copies between two remote hosts are also permitted. .Pp The options are as follows: .Bl -tag -width Ds -.It Fl 1 -Forces -.Nm -to use protocol 1. -.It Fl 2 -Forces -.Nm -to use protocol 2. .It Fl 3 Copies between two remote hosts are transferred through the local host. Without this option the data is copied directly between the two remote @@ -136,10 +128,8 @@ For full details of the options listed below, and their possible values, see .It CertificateFile .It ChallengeResponseAuthentication .It CheckHostIP -.It Cipher .It Ciphers .It Compression -.It CompressionLevel .It ConnectionAttempts .It ConnectTimeout .It ControlMaster @@ -170,14 +160,11 @@ For full details of the options listed below, and their possible values, see .It PKCS11Provider .It Port .It PreferredAuthentications -.It Protocol .It ProxyCommand .It ProxyJump .It PubkeyAcceptedKeyTypes .It PubkeyAuthentication .It RekeyLimit -.It RhostsRSAAuthentication -.It RSAAuthentication .It SendEnv .It ServerAliveInterval .It ServerAliveCountMax diff --git a/scp.c b/scp.c index b4db851980ba..a533eb097412 100644 --- a/scp.c +++ b/scp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scp.c,v 1.187 2016/09/12 01:22:38 deraadt Exp $ */ +/* $OpenBSD: scp.c,v 1.192 2017/05/31 09:15:42 deraadt Exp $ */ /* * scp - secure remote copy. This is basically patched BSD rcp which * uses ssh to do the data transfer (instead of using rcmd). @@ -99,6 +99,9 @@ #include #include #include +#ifdef HAVE_STDINT_H +#include +#endif #include #include #include @@ -403,7 +406,11 @@ main(int argc, char **argv) switch (ch) { /* User-visible flags. */ case '1': + fatal("SSH protocol v.1 is no longer supported"); + break; case '2': + /* Ignored */ + break; case '4': case '6': case 'C': @@ -915,6 +922,11 @@ rsource(char *name, struct stat *statp) (void) response(); } +#define TYPE_OVERFLOW(type, val) \ + ((sizeof(type) == 4 && (val) > INT32_MAX) || \ + (sizeof(type) == 8 && (val) > INT64_MAX) || \ + (sizeof(type) != 4 && sizeof(type) != 8)) + void sink(int argc, char **argv) { @@ -938,6 +950,9 @@ sink(int argc, char **argv) #define mtime tv[1] #define SCREWUP(str) { why = str; goto screwup; } + if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0)) + SCREWUP("Unexpected off_t/time_t size"); + setimes = targisdir = 0; mask = umask(0); if (!pflag) @@ -996,8 +1011,7 @@ sink(int argc, char **argv) ull = strtoull(cp, &cp, 10); if (!cp || *cp++ != ' ') SCREWUP("mtime.sec not delimited"); - if ((time_t)ull < 0 || - (unsigned long long)(time_t)ull != ull) + if (TYPE_OVERFLOW(time_t, ull)) setimes = 0; /* out of range */ mtime.tv_sec = ull; mtime.tv_usec = strtol(cp, &cp, 10); @@ -1009,8 +1023,7 @@ sink(int argc, char **argv) ull = strtoull(cp, &cp, 10); if (!cp || *cp++ != ' ') SCREWUP("atime.sec not delimited"); - if ((time_t)ull < 0 || - (unsigned long long)(time_t)ull != ull) + if (TYPE_OVERFLOW(time_t, ull)) setimes = 0; /* out of range */ atime.tv_sec = ull; atime.tv_usec = strtol(cp, &cp, 10); @@ -1043,10 +1056,15 @@ sink(int argc, char **argv) if (*cp++ != ' ') SCREWUP("mode not delimited"); - for (size = 0; isdigit((unsigned char)*cp);) - size = size * 10 + (*cp++ - '0'); - if (*cp++ != ' ') + if (!isdigit((unsigned char)*cp)) + SCREWUP("size not present"); + ull = strtoull(cp, &cp, 10); + if (!cp || *cp++ != ' ') SCREWUP("size not delimited"); + if (TYPE_OVERFLOW(off_t, ull)) + SCREWUP("size out of range"); + size = (off_t)ull; + if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) { run_err("error: unexpected filename: %s", cp); exit(1); @@ -1256,7 +1274,7 @@ void usage(void) { (void) fprintf(stderr, - "usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n" + "usage: scp [-346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n" " [-l limit] [-o ssh_option] [-P port] [-S program]\n" " [[user@]host1:]file1 ... [[user@]host2:]file2\n"); exit(1); @@ -1350,11 +1368,7 @@ allocbuf(BUF *bp, int fd, int blksize) #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ if (bp->cnt >= size) return (bp); - if (bp->buf == NULL) - bp->buf = xmalloc(size); - else - bp->buf = xreallocarray(bp->buf, 1, size); - memset(bp->buf, 0, size); + bp->buf = xrecallocarray(bp->buf, bp->cnt, size, 1); bp->cnt = size; return (bp); } diff --git a/servconf.c b/servconf.c index 56b831652f53..2c321a4ad4f3 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.306 2017/03/14 07:19:07 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.312 2017/10/02 19:33:20 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -149,7 +149,7 @@ initialize_server_options(ServerOptions *options) options->num_authkeys_files = 0; options->num_accept_env = 0; options->permit_tun = -1; - options->num_permitted_opens = -1; + options->permitted_opens = NULL; options->adm_forced_command = NULL; options->chroot_directory = NULL; options->authorized_keys_command = NULL; @@ -164,6 +164,7 @@ initialize_server_options(ServerOptions *options) options->version_addendum = NULL; options->fingerprint_hash = -1; options->disable_forwarding = -1; + options->expose_userauth_info = -1; } /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ @@ -333,6 +334,8 @@ fill_default_server_options(ServerOptions *options) options->fingerprint_hash = SSH_FP_HASH_DEFAULT; if (options->disable_forwarding == -1) options->disable_forwarding = 0; + if (options->expose_userauth_info == -1) + options->expose_userauth_info = 0; assemble_algorithms(options); @@ -418,6 +421,7 @@ typedef enum { sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, sStreamLocalBindMask, sStreamLocalBindUnlink, sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, + sExposeAuthInfo, sDeprecated, sIgnore, sUnsupported } ServerOpCodes; @@ -449,7 +453,7 @@ static struct { { "keyregenerationinterval", sDeprecated, SSHCFG_GLOBAL }, { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL }, { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, - { "loglevel", sLogLevel, SSHCFG_GLOBAL }, + { "loglevel", sLogLevel, SSHCFG_ALL }, { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL }, { "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL }, { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, @@ -561,6 +565,7 @@ static struct { { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, { "disableforwarding", sDisableForwarding, SSHCFG_ALL }, + { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, { NULL, sBadOption, 0 } }; @@ -692,6 +697,44 @@ process_queued_listen_addrs(ServerOptions *options) options->num_queued_listens = 0; } +/* + * Inform channels layer of permitopen options from configuration. + */ +void +process_permitopen(struct ssh *ssh, ServerOptions *options) +{ + u_int i; + int port; + char *host, *arg, *oarg; + + channel_clear_adm_permitted_opens(ssh); + if (options->num_permitted_opens == 0) + return; /* permit any */ + + /* handle keywords: "any" / "none" */ + if (options->num_permitted_opens == 1 && + strcmp(options->permitted_opens[0], "any") == 0) + return; + if (options->num_permitted_opens == 1 && + strcmp(options->permitted_opens[0], "none") == 0) { + channel_disable_adm_local_opens(ssh); + return; + } + /* Otherwise treat it as a list of permitted host:port */ + for (i = 0; i < options->num_permitted_opens; i++) { + oarg = arg = xstrdup(options->permitted_opens[i]); + host = hpdelim(&arg); + if (host == NULL) + fatal("%s: missing host in PermitOpen", __func__); + host = cleanhostname(host); + if (arg == NULL || ((port = permitopen_port(arg)) < 0)) + fatal("%s: bad port number in PermitOpen", __func__); + /* Send it to channels layer */ + channel_add_adm_permitted_opens(ssh, host, port); + free(oarg); + } +} + struct connection_info * get_connection_info(int populate, int use_dns) { @@ -935,13 +978,6 @@ static const struct multistate multistate_gatewayports[] = { { "no", 0 }, { NULL, -1 } }; -static const struct multistate multistate_privsep[] = { - { "yes", PRIVSEP_NOSANDBOX }, - { "sandbox", PRIVSEP_ON }, - { "nosandbox", PRIVSEP_NOSANDBOX }, - { "no", PRIVSEP_OFF }, - { NULL, -1 } -}; static const struct multistate multistate_tcpfwd[] = { { "yes", FORWARD_ALLOW }, { "all", FORWARD_ALLOW }, @@ -956,7 +992,7 @@ process_server_config_line(ServerOptions *options, char *line, const char *filename, int linenum, int *activep, struct connection_info *connectinfo) { - char *cp, **charptr, *arg, *p; + char *cp, **charptr, *arg, *arg2, *p; int cmdline = 0, *intptr, value, value2, n, port; SyslogFacility *log_facility_ptr; LogLevel *log_level_ptr; @@ -1352,7 +1388,7 @@ process_server_config_line(ServerOptions *options, char *line, if (value == SYSLOG_LEVEL_NOT_SET) fatal("%.200s line %d: unsupported log level '%s'", filename, linenum, arg ? arg : ""); - if (*log_level_ptr == -1) + if (*activep && *log_level_ptr == -1) *log_level_ptr = (LogLevel) value; break; @@ -1627,24 +1663,18 @@ process_server_config_line(ServerOptions *options, char *line, if (!arg || *arg == '\0') fatal("%s line %d: missing PermitOpen specification", filename, linenum); - n = options->num_permitted_opens; /* modified later */ - if (strcmp(arg, "any") == 0) { - if (*activep && n == -1) { - channel_clear_adm_permitted_opens(); - options->num_permitted_opens = 0; - } - break; - } - if (strcmp(arg, "none") == 0) { - if (*activep && n == -1) { + i = options->num_permitted_opens; /* modified later */ + if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) { + if (*activep && i == 0) { options->num_permitted_opens = 1; - channel_disable_adm_local_opens(); + options->permitted_opens = xcalloc(1, + sizeof(*options->permitted_opens)); + options->permitted_opens[0] = xstrdup(arg); } break; } - if (*activep && n == -1) - channel_clear_adm_permitted_opens(); for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { + arg2 = xstrdup(arg); p = hpdelim(&arg); if (p == NULL) fatal("%s line %d: missing host in PermitOpen", @@ -1653,9 +1683,16 @@ process_server_config_line(ServerOptions *options, char *line, if (arg == NULL || ((port = permitopen_port(arg)) < 0)) fatal("%s line %d: bad port number in " "PermitOpen", filename, linenum); - if (*activep && n == -1) - options->num_permitted_opens = - channel_add_adm_permitted_opens(p, port); + if (*activep && i == 0) { + options->permitted_opens = xrecallocarray( + options->permitted_opens, + options->num_permitted_opens, + options->num_permitted_opens + 1, + sizeof(*options->permitted_opens)); + i = options->num_permitted_opens++; + options->permitted_opens[i] = arg2; + } else + free(arg2); } break; @@ -1842,6 +1879,10 @@ process_server_config_line(ServerOptions *options, char *line, options->fingerprint_hash = value; break; + case sExposeAuthInfo: + intptr = &options->expose_userauth_info; + goto parse_flag; + case sDeprecated: case sIgnore: case sUnsupported: @@ -1980,6 +2021,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(allow_streamlocal_forwarding); M_CP_INTOPT(allow_agent_forwarding); M_CP_INTOPT(disable_forwarding); + M_CP_INTOPT(expose_userauth_info); M_CP_INTOPT(permit_tun); M_CP_INTOPT(fwd_opts.gateway_ports); M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink); @@ -1996,6 +2038,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(ip_qos_bulk); M_CP_INTOPT(rekey_limit); M_CP_INTOPT(rekey_interval); + M_CP_INTOPT(log_level); /* * The bind_mask is a mode_t that may be unsigned, so we can't use @@ -2020,6 +2063,13 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \ } \ } while(0) +#define M_CP_STRARRAYOPT_ALLOC(n, num_n) do { \ + if (src->num_n != 0) { \ + dst->n = xcalloc(src->num_n, sizeof(*dst->n)); \ + M_CP_STRARRAYOPT(n, num_n); \ + dst->num_n = src->num_n; \ + } \ +} while(0) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); @@ -2050,6 +2100,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) #undef M_CP_INTOPT #undef M_CP_STROPT #undef M_CP_STRARRAYOPT +#undef M_CP_STRARRAYOPT_ALLOC void parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, @@ -2278,6 +2329,7 @@ dump_config(ServerOptions *o) dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); + dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info); /* string arguments */ dump_cfg_string(sPidFile, o->pid_file); @@ -2347,5 +2399,12 @@ dump_config(ServerOptions *o) printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit, o->rekey_interval); - channel_print_adm_permitted_opens(); + printf("permitopen"); + if (o->num_permitted_opens == 0) + printf(" any"); + else { + for (i = 0; i < o->num_permitted_opens; i++) + printf(" %s", o->permitted_opens[i]); + } + printf("\n"); } diff --git a/servconf.h b/servconf.h index 5853a97470ae..1dca702e6acb 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.123 2016/11/30 03:00:05 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.126 2017/10/02 19:33:20 djm Exp $ */ /* * Author: Tatu Ylonen @@ -48,12 +48,19 @@ #define FORWARD_LOCAL (1<<1) #define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL) +/* PermitOpen */ +#define PERMITOPEN_ANY 0 +#define PERMITOPEN_NONE -2 + #define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ #define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */ /* Magic name for internal sftp-server */ #define INTERNAL_SFTP_NAME "internal-sftp" +struct ssh; +struct fwd_perm_list; + typedef struct { u_int num_ports; u_int ports_from_cmdline; @@ -169,7 +176,8 @@ typedef struct { int permit_tun; - int num_permitted_opens; + char **permitted_opens; + u_int num_permitted_opens; /* May also be one of PERMITOPEN_* */ char *chroot_directory; char *revoked_keys_file; @@ -189,6 +197,7 @@ typedef struct { char *auth_methods[MAX_AUTH_METHODS]; int fingerprint_hash; + int expose_userauth_info; } ServerOptions; /* Information about the incoming connection as used by Match */ @@ -228,6 +237,7 @@ struct connection_info { M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \ M_CP_STRARRAYOPT(accept_env, num_accept_env); \ M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \ + M_CP_STRARRAYOPT_ALLOC(permitted_opens, num_permitted_opens); \ } while (0) struct connection_info *get_connection_info(int, int); @@ -235,6 +245,7 @@ void initialize_server_options(ServerOptions *); void fill_default_server_options(ServerOptions *); int process_server_config_line(ServerOptions *, char *, const char *, int, int *, struct connection_info *); +void process_permitopen(struct ssh *ssh, ServerOptions *options); void load_server_config(const char *, Buffer *); void parse_server_config(ServerOptions *, const char *, Buffer *, struct connection_info *); diff --git a/serverloop.c b/serverloop.c index 2976f55943b4..24bbae322c34 100644 --- a/serverloop.c +++ b/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.191 2017/02/01 02:59:09 dtucker Exp $ */ +/* $OpenBSD: serverloop.c,v 1.198 2017/09/12 06:35:32 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -165,7 +165,7 @@ sigterm_handler(int sig) } static void -client_alive_check(void) +client_alive_check(struct ssh *ssh) { int channel_id; @@ -179,12 +179,13 @@ client_alive_check(void) * send a bogus global/channel request with "wantreply", * we should get back a failure */ - if ((channel_id = channel_find_open()) == -1) { + if ((channel_id = channel_find_open(ssh)) == -1) { packet_start(SSH2_MSG_GLOBAL_REQUEST); packet_put_cstring("keepalive@openssh.com"); packet_put_char(1); /* boolean: want reply */ } else { - channel_request_start(channel_id, "keepalive@openssh.com", 1); + channel_request_start(ssh, channel_id, + "keepalive@openssh.com", 1); } packet_send(); } @@ -196,7 +197,8 @@ client_alive_check(void) * for the duration of the wait (0 = infinite). */ static void -wait_until_can_do_something(int connection_in, int connection_out, +wait_until_can_do_something(struct ssh *ssh, + int connection_in, int connection_out, fd_set **readsetp, fd_set **writesetp, int *maxfdp, u_int *nallocp, u_int64_t max_time_ms) { @@ -204,10 +206,11 @@ wait_until_can_do_something(int connection_in, int connection_out, int ret; time_t minwait_secs = 0; int client_alive_scheduled = 0; + static time_t last_client_time; /* Allocate and update select() masks for channel descriptors. */ - channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, - &minwait_secs, 0); + channel_prepare_select(ssh, readsetp, writesetp, maxfdp, + nallocp, &minwait_secs); /* XXX need proper deadline system for rekey/client alive */ if (minwait_secs != 0) @@ -268,8 +271,19 @@ wait_until_can_do_something(int connection_in, int connection_out, memset(*writesetp, 0, *nallocp); if (errno != EINTR) error("select: %.100s", strerror(errno)); - } else if (ret == 0 && client_alive_scheduled) - client_alive_check(); + } else if (client_alive_scheduled) { + time_t now = monotime(); + + if (ret == 0) { /* timeout */ + client_alive_check(ssh); + } else if (FD_ISSET(connection_in, *readsetp)) { + last_client_time = now; + } else if (last_client_time != 0 && last_client_time + + options.client_alive_interval <= now) { + client_alive_check(ssh); + last_client_time = now; + } + } notify_done(*readsetp); } @@ -279,9 +293,8 @@ wait_until_can_do_something(int connection_in, int connection_out, * in buffers and processed later. */ static int -process_input(fd_set *readset, int connection_in) +process_input(struct ssh *ssh, fd_set *readset, int connection_in) { - struct ssh *ssh = active_state; /* XXX */ int len; char buf[16384]; @@ -321,13 +334,13 @@ process_output(fd_set *writeset, int connection_out) } static void -process_buffered_input_packets(void) +process_buffered_input_packets(struct ssh *ssh) { - dispatch_run(DISPATCH_NONBLOCK, NULL, active_state); + ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, NULL); } static void -collect_children(void) +collect_children(struct ssh *ssh) { pid_t pid; sigset_t oset, nset; @@ -342,14 +355,14 @@ collect_children(void) while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || (pid < 0 && errno == EINTR)) if (pid > 0) - session_close_by_pid(pid, status); + session_close_by_pid(ssh, pid, status); child_terminated = 0; } sigprocmask(SIG_SETMASK, &oset, NULL); } void -server_loop2(Authctxt *authctxt) +server_loop2(struct ssh *ssh, Authctxt *authctxt) { fd_set *readset = NULL, *writeset = NULL; int max_fd; @@ -377,18 +390,17 @@ server_loop2(Authctxt *authctxt) server_init_dispatch(); for (;;) { - process_buffered_input_packets(); + process_buffered_input_packets(ssh); - if (!ssh_packet_is_rekeying(active_state) && + if (!ssh_packet_is_rekeying(ssh) && packet_not_very_much_data_to_write()) - channel_output_poll(); - if (options.rekey_interval > 0 && - !ssh_packet_is_rekeying(active_state)) + channel_output_poll(ssh); + if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(ssh)) rekey_timeout_ms = packet_get_rekey_timeout() * 1000; else rekey_timeout_ms = 0; - wait_until_can_do_something(connection_in, connection_out, + wait_until_can_do_something(ssh, connection_in, connection_out, &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms); if (received_sigterm) { @@ -397,27 +409,27 @@ server_loop2(Authctxt *authctxt) cleanup_exit(255); } - collect_children(); - if (!ssh_packet_is_rekeying(active_state)) - channel_after_select(readset, writeset); - if (process_input(readset, connection_in) < 0) + collect_children(ssh); + if (!ssh_packet_is_rekeying(ssh)) + channel_after_select(ssh, readset, writeset); + if (process_input(ssh, readset, connection_in) < 0) break; process_output(writeset, connection_out); } - collect_children(); + collect_children(ssh); free(readset); free(writeset); /* free all channels, no more reads and writes */ - channel_free_all(); + channel_free_all(ssh); /* free remaining sessions, e.g. remove wtmp entries */ - session_destroy_all(NULL); + session_destroy_all(ssh, NULL); } static int -server_input_keep_alive(int type, u_int32_t seq, void *ctxt) +server_input_keep_alive(int type, u_int32_t seq, struct ssh *ssh) { debug("Got %d/%u for keepalive", type, seq); /* @@ -430,7 +442,7 @@ server_input_keep_alive(int type, u_int32_t seq, void *ctxt) } static Channel * -server_request_direct_tcpip(int *reason, const char **errmsg) +server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg) { Channel *c = NULL; char *target, *originator; @@ -448,7 +460,7 @@ server_request_direct_tcpip(int *reason, const char **errmsg) /* XXX fine grained permissions */ if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && !no_port_forwarding_flag && !options.disable_forwarding) { - c = channel_connect_to_port(target, target_port, + c = channel_connect_to_port(ssh, target, target_port, "direct-tcpip", "direct-tcpip", reason, errmsg); } else { logit("refused local port forward: " @@ -465,7 +477,7 @@ server_request_direct_tcpip(int *reason, const char **errmsg) } static Channel * -server_request_direct_streamlocal(void) +server_request_direct_streamlocal(struct ssh *ssh) { Channel *c = NULL; char *target, *originator; @@ -487,7 +499,7 @@ server_request_direct_streamlocal(void) if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 && !no_port_forwarding_flag && !options.disable_forwarding && (pw->pw_uid == 0 || use_privsep)) { - c = channel_connect_to_path(target, + c = channel_connect_to_path(ssh, target, "direct-streamlocal@openssh.com", "direct-streamlocal"); } else { logit("refused streamlocal port forward: " @@ -502,7 +514,7 @@ server_request_direct_streamlocal(void) } static Channel * -server_request_tun(void) +server_request_tun(struct ssh *ssh) { Channel *c = NULL; int mode, tun; @@ -532,12 +544,12 @@ server_request_tun(void) sock = tun_open(tun, mode); if (sock < 0) goto done; - c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, + c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); c->datagram = 1; #if defined(SSH_TUN_FILTER) if (mode == SSH_TUNMODE_POINTOPOINT) - channel_register_filter(c->self, sys_tun_infilter, + channel_register_filter(ssh, c->self, sys_tun_infilter, sys_tun_outfilter, NULL, NULL); #endif @@ -548,7 +560,7 @@ server_request_tun(void) } static Channel * -server_request_session(void) +server_request_session(struct ssh *ssh) { Channel *c; @@ -566,20 +578,20 @@ server_request_session(void) * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all * CHANNEL_REQUEST messages is registered. */ - c = channel_new("session", SSH_CHANNEL_LARVAL, + c = channel_new(ssh, "session", SSH_CHANNEL_LARVAL, -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, 0, "server-session", 1); if (session_open(the_authctxt, c->self) != 1) { debug("session open failed, free channel %d", c->self); - channel_free(c); + channel_free(ssh, c); return NULL; } - channel_register_cleanup(c->self, session_close_by_channel, 0); + channel_register_cleanup(ssh, c->self, session_close_by_channel, 0); return c; } static int -server_input_channel_open(int type, u_int32_t seq, void *ctxt) +server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = NULL; char *ctype; @@ -596,17 +608,18 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt) ctype, rchan, rwindow, rmaxpack); if (strcmp(ctype, "session") == 0) { - c = server_request_session(); + c = server_request_session(ssh); } else if (strcmp(ctype, "direct-tcpip") == 0) { - c = server_request_direct_tcpip(&reason, &errmsg); + c = server_request_direct_tcpip(ssh, &reason, &errmsg); } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) { - c = server_request_direct_streamlocal(); + c = server_request_direct_streamlocal(ssh); } else if (strcmp(ctype, "tun@openssh.com") == 0) { - c = server_request_tun(); + c = server_request_tun(ssh); } if (c != NULL) { debug("server_input_channel_open: confirm %s", ctype); c->remote_id = rchan; + c->have_remote_id = 1; c->remote_window = rwindow; c->remote_maxpacket = rmaxpack; if (c->type != SSH_CHANNEL_CONNECTING) { @@ -633,9 +646,8 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt) } static int -server_input_hostkeys_prove(struct sshbuf **respp) +server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) { - struct ssh *ssh = active_state; /* XXX */ struct sshbuf *resp = NULL; struct sshbuf *sigbuf = NULL; struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; @@ -703,7 +715,7 @@ server_input_hostkeys_prove(struct sshbuf **respp) } static int -server_input_global_request(int type, u_int32_t seq, void *ctxt) +server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) { char *rtype; int want_reply; @@ -738,7 +750,7 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) packet_send_debug("Server has disabled port forwarding."); } else { /* Start listening on the port */ - success = channel_setup_remote_fwd_listener(&fwd, + success = channel_setup_remote_fwd_listener(ssh, &fwd, &allocated_listen_port, &options.fwd_opts); } free(fwd.listen_host); @@ -756,7 +768,7 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) debug("%s: cancel-tcpip-forward addr %s port %d", __func__, fwd.listen_host, fwd.listen_port); - success = channel_cancel_rport_listener(&fwd); + success = channel_cancel_rport_listener(ssh, &fwd); free(fwd.listen_host); } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) { struct Forward fwd; @@ -775,7 +787,7 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) "streamlocal forwarding."); } else { /* Start listening on the socket */ - success = channel_setup_remote_fwd_listener( + success = channel_setup_remote_fwd_listener(ssh, &fwd, NULL, &options.fwd_opts); } free(fwd.listen_path); @@ -787,19 +799,19 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) debug("%s: cancel-streamlocal-forward path %s", __func__, fwd.listen_path); - success = channel_cancel_rport_listener(&fwd); + success = channel_cancel_rport_listener(ssh, &fwd); free(fwd.listen_path); } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { no_more_sessions = 1; success = 1; } else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) { - success = server_input_hostkeys_prove(&resp); + success = server_input_hostkeys_prove(ssh, &resp); } if (want_reply) { packet_start(success ? SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); if (success && resp != NULL) - ssh_packet_put_raw(active_state, sshbuf_ptr(resp), + ssh_packet_put_raw(ssh, sshbuf_ptr(resp), sshbuf_len(resp)); packet_send(); packet_write_wait(); @@ -810,7 +822,7 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) } static int -server_input_channel_req(int type, u_int32_t seq, void *ctxt) +server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) { Channel *c; int id, reply, success = 0; @@ -823,16 +835,19 @@ server_input_channel_req(int type, u_int32_t seq, void *ctxt) debug("server_input_channel_req: channel %d request %s reply %d", id, rtype, reply); - if ((c = channel_lookup(id)) == NULL) + if ((c = channel_lookup(ssh, id)) == NULL) packet_disconnect("server_input_channel_req: " "unknown channel %d", id); if (!strcmp(rtype, "eow@openssh.com")) { packet_check_eom(); - chan_rcvd_eow(c); + chan_rcvd_eow(ssh, c); } else if ((c->type == SSH_CHANNEL_LARVAL || c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0) - success = session_input_channel_req(c, rtype); + success = session_input_channel_req(ssh, c, rtype); if (reply && !(c->flags & CHAN_CLOSE_SENT)) { + if (!c->have_remote_id) + fatal("%s: channel %d: no remote_id", + __func__, c->self); packet_start(success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); packet_put_int(c->remote_id); diff --git a/serverloop.h b/serverloop.h index d5fbda16fa62..fd2cf63f74e7 100644 --- a/serverloop.h +++ b/serverloop.h @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.h,v 1.7 2016/08/13 17:47:41 markus Exp $ */ +/* $OpenBSD: serverloop.h,v 1.8 2017/09/12 06:32:07 djm Exp $ */ /* * Author: Tatu Ylonen @@ -21,6 +21,8 @@ #ifndef SERVERLOOP_H #define SERVERLOOP_H -void server_loop2(Authctxt *); +struct ssh; + +void server_loop2(struct ssh *, Authctxt *); #endif diff --git a/session.c b/session.c index a08aa69d1679..4bccb62d1e4d 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.286 2016/11/30 03:00:05 djm Exp $ */ +/* $OpenBSD: session.c,v 1.292 2017/09/12 06:32:07 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -94,6 +94,7 @@ #include "kex.h" #include "monitor_wrap.h" #include "sftp.h" +#include "atomicio.h" #if defined(KRB5) && defined(USE_AFS) #include @@ -112,29 +113,28 @@ /* func */ Session *session_new(void); -void session_set_fds(Session *, int, int, int, int, int); +void session_set_fds(struct ssh *, Session *, int, int, int, int, int); void session_pty_cleanup(Session *); void session_proctitle(Session *); -int session_setup_x11fwd(Session *); -int do_exec_pty(Session *, const char *); -int do_exec_no_pty(Session *, const char *); -int do_exec(Session *, const char *); -void do_login(Session *, const char *); +int session_setup_x11fwd(struct ssh *, Session *); +int do_exec_pty(struct ssh *, Session *, const char *); +int do_exec_no_pty(struct ssh *, Session *, const char *); +int do_exec(struct ssh *, Session *, const char *); +void do_login(struct ssh *, Session *, const char *); +void do_child(struct ssh *, Session *, const char *); #ifdef LOGIN_NEEDS_UTMPX static void do_pre_login(Session *s); #endif -void do_child(Session *, const char *); void do_motd(void); int check_quietlogin(Session *, const char *); -static void do_authenticated2(Authctxt *); +static void do_authenticated2(struct ssh *, Authctxt *); -static int session_pty_req(Session *); +static int session_pty_req(struct ssh *, Session *); /* import */ extern ServerOptions options; extern char *__progname; -extern int log_stderr; extern int debug_flag; extern u_int utmp_len; extern int startup_pipe; @@ -161,6 +161,9 @@ login_cap_t *lc; static int is_child = 0; static int in_chroot = 0; +/* File containing userauth info, if ExposeAuthInfo set */ +static char *auth_info_file = NULL; + /* Name and directory of socket for authentication agent forwarding. */ static char *auth_sock_name = NULL; static char *auth_sock_dir = NULL; @@ -180,7 +183,7 @@ auth_sock_cleanup_proc(struct passwd *pw) } static int -auth_input_request_forwarding(struct passwd * pw) +auth_input_request_forwarding(struct ssh *ssh, struct passwd * pw) { Channel *nc; int sock = -1; @@ -220,7 +223,7 @@ auth_input_request_forwarding(struct passwd * pw) goto authsock_err; /* Allocate a channel for the authentication agent socket. */ - nc = channel_new("auth socket", + nc = channel_new(ssh, "auth socket", SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "auth socket", 1); @@ -250,8 +253,42 @@ display_loginmsg(void) } } +static void +prepare_auth_info_file(struct passwd *pw, struct sshbuf *info) +{ + int fd = -1, success = 0; + + if (!options.expose_userauth_info || info == NULL) + return; + + temporarily_use_uid(pw); + auth_info_file = xstrdup("/tmp/sshauth.XXXXXXXXXXXXXXX"); + if ((fd = mkstemp(auth_info_file)) == -1) { + error("%s: mkstemp: %s", __func__, strerror(errno)); + goto out; + } + if (atomicio(vwrite, fd, sshbuf_mutable_ptr(info), + sshbuf_len(info)) != sshbuf_len(info)) { + error("%s: write: %s", __func__, strerror(errno)); + goto out; + } + if (close(fd) != 0) { + error("%s: close: %s", __func__, strerror(errno)); + goto out; + } + success = 1; + out: + if (!success) { + if (fd != -1) + close(fd); + free(auth_info_file); + auth_info_file = NULL; + } + restore_uid(); +} + void -do_authenticated(Authctxt *authctxt) +do_authenticated(struct ssh *ssh, Authctxt *authctxt) { setproctitle("%s", authctxt->pw->pw_name); @@ -259,14 +296,17 @@ do_authenticated(Authctxt *authctxt) /* XXX - streamlocal? */ if (no_port_forwarding_flag || options.disable_forwarding || (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) - channel_disable_adm_local_opens(); + channel_disable_adm_local_opens(ssh); else - channel_permit_all_opens(); + channel_permit_all_opens(ssh); auth_debug_send(); - do_authenticated2(authctxt); - do_cleanup(authctxt); + prepare_auth_info_file(authctxt->pw, authctxt->session_info); + + do_authenticated2(ssh, authctxt); + + do_cleanup(ssh, authctxt); } /* Check untrusted xauth strings for metacharacters */ @@ -291,7 +331,7 @@ xauth_valid_string(const char *s) * setting up file descriptors and such. */ int -do_exec_no_pty(Session *s, const char *command) +do_exec_no_pty(struct ssh *ssh, Session *s, const char *command) { pid_t pid; @@ -364,10 +404,6 @@ do_exec_no_pty(Session *s, const char *command) case 0: is_child = 1; - /* Child. Reinitialize the log since the pid has changed. */ - log_init(__progname, options.log_level, - options.log_facility, log_stderr); - /* * Create a new session and process group since the 4.4BSD * setlogin() affects the entire process group. @@ -420,7 +456,7 @@ do_exec_no_pty(Session *s, const char *command) #endif /* Do processing for the child (exec command etc). */ - do_child(s, command); + do_child(ssh, s, command); /* NOTREACHED */ default: break; @@ -451,7 +487,7 @@ do_exec_no_pty(Session *s, const char *command) close(pout[1]); close(perr[1]); - session_set_fds(s, pin[1], pout[0], perr[0], + session_set_fds(ssh, s, pin[1], pout[0], perr[0], s->is_subsystem, 0); #else /* We are the parent. Close the child sides of the socket pairs. */ @@ -475,7 +511,7 @@ do_exec_no_pty(Session *s, const char *command) * lastlog, and other such operations. */ int -do_exec_pty(Session *s, const char *command) +do_exec_pty(struct ssh *ssh, Session *s, const char *command) { int fdout, ptyfd, ttyfd, ptymaster; pid_t pid; @@ -522,9 +558,6 @@ do_exec_pty(Session *s, const char *command) close(fdout); close(ptymaster); - /* Child. Reinitialize the log because the pid has changed. */ - log_init(__progname, options.log_level, - options.log_facility, log_stderr); /* Close the master side of the pseudo tty. */ close(ptyfd); @@ -547,13 +580,13 @@ do_exec_pty(Session *s, const char *command) cray_init_job(s->pw); /* set up cray jid and tmpdir */ #endif /* _UNICOS */ #ifndef HAVE_OSF_SIA - do_login(s, command); + do_login(ssh, s, command); #endif /* * Do common processing for the child, such as execing * the command. */ - do_child(s, command); + do_child(ssh, s, command); /* NOTREACHED */ default: break; @@ -575,7 +608,7 @@ do_exec_pty(Session *s, const char *command) s->ptymaster = ptymaster; packet_set_interactive(1, options.ip_qos_interactive, options.ip_qos_bulk); - session_set_fds(s, ptyfd, fdout, -1, 1, 1); + session_set_fds(ssh, s, ptyfd, fdout, -1, 1, 1); return 0; } @@ -613,9 +646,8 @@ do_pre_login(Session *s) * to be forced, execute that instead. */ int -do_exec(Session *s, const char *command) +do_exec(struct ssh *ssh, Session *s, const char *command) { - struct ssh *ssh = active_state; /* XXX */ int ret; const char *forced = NULL, *tty = NULL; char session_type[1024]; @@ -674,9 +706,9 @@ do_exec(Session *s, const char *command) } #endif if (s->ttyfd != -1) - ret = do_exec_pty(s, command); + ret = do_exec_pty(ssh, s, command); else - ret = do_exec_no_pty(s, command); + ret = do_exec_no_pty(ssh, s, command); original_command = NULL; @@ -692,9 +724,8 @@ do_exec(Session *s, const char *command) /* administrative, login(1)-like work */ void -do_login(Session *s, const char *command) +do_login(struct ssh *ssh, Session *s, const char *command) { - struct ssh *ssh = active_state; /* XXX */ socklen_t fromlen; struct sockaddr_storage from; struct passwd * pw = s->pw; @@ -791,65 +822,6 @@ check_quietlogin(Session *s, const char *command) return 0; } -/* - * Sets the value of the given variable in the environment. If the variable - * already exists, its value is overridden. - */ -void -child_set_env(char ***envp, u_int *envsizep, const char *name, - const char *value) -{ - char **env; - u_int envsize; - u_int i, namelen; - - if (strchr(name, '=') != NULL) { - error("Invalid environment variable \"%.100s\"", name); - return; - } - - /* - * If we're passed an uninitialized list, allocate a single null - * entry before continuing. - */ - if (*envp == NULL && *envsizep == 0) { - *envp = xmalloc(sizeof(char *)); - *envp[0] = NULL; - *envsizep = 1; - } - - /* - * Find the slot where the value should be stored. If the variable - * already exists, we reuse the slot; otherwise we append a new slot - * at the end of the array, expanding if necessary. - */ - env = *envp; - namelen = strlen(name); - for (i = 0; env[i]; i++) - if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=') - break; - if (env[i]) { - /* Reuse the slot. */ - free(env[i]); - } else { - /* New variable. Expand if necessary. */ - envsize = *envsizep; - if (i >= envsize - 1) { - if (envsize >= 1000) - fatal("child_set_env: too many env vars"); - envsize += 50; - env = (*envp) = xreallocarray(env, envsize, sizeof(char *)); - *envsizep = envsize; - } - /* Need to set the NULL pointer at end of array beyond the new slot. */ - env[i + 1] = NULL; - } - - /* Allocate space and format the variable in the appropriate slot. */ - env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1); - snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value); -} - /* * Reads environment variables from the given file and adds/overrides them * into the environment. If the file does not exist, this does nothing. @@ -951,8 +923,9 @@ read_etc_default_login(char ***env, u_int *envsize, uid_t uid) } #endif /* HAVE_ETC_DEFAULT_LOGIN */ -void -copy_environment(char **source, char ***env, u_int *envsize) +static void +copy_environment_blacklist(char **source, char ***env, u_int *envsize, + const char *blacklist) { char *var_name, *var_val; int i; @@ -968,17 +941,25 @@ copy_environment(char **source, char ***env, u_int *envsize) } *var_val++ = '\0'; - debug3("Copy environment: %s=%s", var_name, var_val); - child_set_env(env, envsize, var_name, var_val); + if (blacklist == NULL || + match_pattern_list(var_name, blacklist, 0) != 1) { + debug3("Copy environment: %s=%s", var_name, var_val); + child_set_env(env, envsize, var_name, var_val); + } free(var_name); } } -static char ** -do_setup_env(Session *s, const char *shell) +void +copy_environment(char **source, char ***env, u_int *envsize) +{ + copy_environment_blacklist(source, env, envsize, NULL); +} + +static char ** +do_setup_env(struct ssh *ssh, Session *s, const char *shell) { - struct ssh *ssh = active_state; /* XXX */ char buf[256]; u_int i, envsize; char **env, *laddr; @@ -1085,6 +1066,8 @@ do_setup_env(Session *s, const char *shell) free(laddr); child_set_env(&env, &envsize, "SSH_CONNECTION", buf); + if (auth_info_file != NULL) + child_set_env(&env, &envsize, "SSH_USER_AUTH", auth_info_file); if (s->ttyfd != -1) child_set_env(&env, &envsize, "SSH_TTY", s->tty); if (s->term) @@ -1134,12 +1117,16 @@ do_setup_env(Session *s, const char *shell) if (options.use_pam) { char **p; + /* + * Don't allow SSH_AUTH_INFO variables posted to PAM to leak + * back into the environment. + */ p = fetch_pam_child_environment(); - copy_environment(p, &env, &envsize); + copy_environment_blacklist(p, &env, &envsize, "SSH_AUTH_INFO*"); free_pam_environment(p); p = fetch_pam_environment(); - copy_environment(p, &env, &envsize); + copy_environment_blacklist(p, &env, &envsize, "SSH_AUTH_INFO*"); free_pam_environment(p); } #endif /* USE_PAM */ @@ -1431,7 +1418,7 @@ do_pwchange(Session *s) } static void -child_close_fds(void) +child_close_fds(struct ssh *ssh) { extern int auth_sock; @@ -1451,7 +1438,7 @@ child_close_fds(void) * open in the parent. */ /* XXX better use close-on-exec? -markus */ - channel_close_all(); + channel_close_all(ssh); /* * Close any extra file descriptors. Note that there may still be @@ -1475,7 +1462,7 @@ child_close_fds(void) */ #define ARGV_MAX 10 void -do_child(Session *s, const char *command) +do_child(struct ssh *ssh, Session *s, const char *command) { extern char **environ; char **env; @@ -1486,11 +1473,12 @@ do_child(Session *s, const char *command) /* remove hostkey from the child's memory */ destroy_sensitive_data(); + packet_clear_keys(); /* Force a password change */ if (s->authctxt->force_pwchange) { do_setusercontext(pw); - child_close_fds(); + child_close_fds(ssh); do_pwchange(s); exit(1); } @@ -1539,7 +1527,7 @@ do_child(Session *s, const char *command) * Make sure $SHELL points to the shell from the password file, * even if shell is overridden from login.conf */ - env = do_setup_env(s, shell); + env = do_setup_env(ssh, s, shell); #ifdef HAVE_LOGIN_CAP shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); @@ -1552,7 +1540,7 @@ do_child(Session *s, const char *command) * closed before building the environment, as we call * ssh_remote_ipaddr there. */ - child_close_fds(); + child_close_fds(ssh); /* * Must take new environment into use so that .ssh/rc, @@ -1710,8 +1698,8 @@ session_new(void) return NULL; debug2("%s: allocate (allocated %d max %d)", __func__, sessions_nalloc, options.max_sessions); - tmp = xreallocarray(sessions, sessions_nalloc + 1, - sizeof(*sessions)); + tmp = xrecallocarray(sessions, sessions_nalloc, + sessions_nalloc + 1, sizeof(*sessions)); if (tmp == NULL) { error("%s: cannot allocate %d sessions", __func__, sessions_nalloc + 1); @@ -1849,7 +1837,7 @@ session_by_pid(pid_t pid) } static int -session_window_change_req(Session *s) +session_window_change_req(struct ssh *ssh, Session *s) { s->col = packet_get_int(); s->row = packet_get_int(); @@ -1861,7 +1849,7 @@ session_window_change_req(Session *s) } static int -session_pty_req(Session *s) +session_pty_req(struct ssh *ssh, Session *s) { u_int len; int n_bytes; @@ -1914,7 +1902,7 @@ session_pty_req(Session *s) } static int -session_subsystem_req(Session *s) +session_subsystem_req(struct ssh *ssh, Session *s) { struct stat st; u_int len; @@ -1941,7 +1929,7 @@ session_subsystem_req(Session *s) s->is_subsystem = SUBSYSTEM_EXT; debug("subsystem: exec() %s", cmd); } - success = do_exec(s, cmd) == 0; + success = do_exec(ssh, s, cmd) == 0; break; } } @@ -1954,7 +1942,7 @@ session_subsystem_req(Session *s) } static int -session_x11_req(Session *s) +session_x11_req(struct ssh *ssh, Session *s) { int success; @@ -1971,7 +1959,7 @@ session_x11_req(Session *s) if (xauth_valid_string(s->auth_proto) && xauth_valid_string(s->auth_data)) - success = session_setup_x11fwd(s); + success = session_setup_x11fwd(ssh, s); else { success = 0; error("Invalid X11 forwarding data"); @@ -1986,26 +1974,26 @@ session_x11_req(Session *s) } static int -session_shell_req(Session *s) +session_shell_req(struct ssh *ssh, Session *s) { packet_check_eom(); - return do_exec(s, NULL) == 0; + return do_exec(ssh, s, NULL) == 0; } static int -session_exec_req(Session *s) +session_exec_req(struct ssh *ssh, Session *s) { u_int len, success; char *command = packet_get_string(&len); packet_check_eom(); - success = do_exec(s, command) == 0; + success = do_exec(ssh, s, command) == 0; free(command); return success; } static int -session_break_req(Session *s) +session_break_req(struct ssh *ssh, Session *s) { packet_get_int(); /* ignored */ @@ -2017,7 +2005,7 @@ session_break_req(Session *s) } static int -session_env_req(Session *s) +session_env_req(struct ssh *ssh, Session *s) { char *name, *val; u_int name_len, val_len, i; @@ -2035,8 +2023,8 @@ session_env_req(Session *s) for (i = 0; i < options.num_accept_env; i++) { if (match_pattern(name, options.accept_env[i])) { debug2("Setting env %d: %s=%s", s->num_env, name, val); - s->env = xreallocarray(s->env, s->num_env + 1, - sizeof(*s->env)); + s->env = xrecallocarray(s->env, s->num_env, + s->num_env + 1, sizeof(*s->env)); s->env[s->num_env].name = name; s->env[s->num_env].val = val; s->num_env++; @@ -2052,7 +2040,7 @@ session_env_req(Session *s) } static int -session_auth_agent_req(Session *s) +session_auth_agent_req(struct ssh *ssh, Session *s) { static int called = 0; packet_check_eom(); @@ -2064,22 +2052,21 @@ session_auth_agent_req(Session *s) return 0; } else { called = 1; - return auth_input_request_forwarding(s->pw); + return auth_input_request_forwarding(ssh, s->pw); } } int -session_input_channel_req(Channel *c, const char *rtype) +session_input_channel_req(struct ssh *ssh, Channel *c, const char *rtype) { int success = 0; Session *s; if ((s = session_by_channel(c->self)) == NULL) { - logit("session_input_channel_req: no session %d req %.100s", - c->self, rtype); + logit("%s: no session %d req %.100s", __func__, c->self, rtype); return 0; } - debug("session_input_channel_req: session %d req %s", s->self, rtype); + debug("%s: session %d req %s", __func__, s->self, rtype); /* * a session is in LARVAL state until a shell, a command @@ -2087,33 +2074,33 @@ session_input_channel_req(Channel *c, const char *rtype) */ if (c->type == SSH_CHANNEL_LARVAL) { if (strcmp(rtype, "shell") == 0) { - success = session_shell_req(s); + success = session_shell_req(ssh, s); } else if (strcmp(rtype, "exec") == 0) { - success = session_exec_req(s); + success = session_exec_req(ssh, s); } else if (strcmp(rtype, "pty-req") == 0) { - success = session_pty_req(s); + success = session_pty_req(ssh, s); } else if (strcmp(rtype, "x11-req") == 0) { - success = session_x11_req(s); + success = session_x11_req(ssh, s); } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) { - success = session_auth_agent_req(s); + success = session_auth_agent_req(ssh, s); } else if (strcmp(rtype, "subsystem") == 0) { - success = session_subsystem_req(s); + success = session_subsystem_req(ssh, s); } else if (strcmp(rtype, "env") == 0) { - success = session_env_req(s); + success = session_env_req(ssh, s); } } if (strcmp(rtype, "window-change") == 0) { - success = session_window_change_req(s); + success = session_window_change_req(ssh, s); } else if (strcmp(rtype, "break") == 0) { - success = session_break_req(s); + success = session_break_req(ssh, s); } return success; } void -session_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr, - int is_tty) +session_set_fds(struct ssh *ssh, Session *s, + int fdin, int fdout, int fderr, int ignore_fderr, int is_tty) { /* * now that have a child and a pipe to the child, @@ -2121,7 +2108,7 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr, */ if (s->chanid == -1) fatal("no channel for session %d", s->self); - channel_set_fds(s->chanid, + channel_set_fds(ssh, s->chanid, fdout, fdin, fderr, ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, 1, is_tty, CHAN_SES_WINDOW_DEFAULT); @@ -2192,40 +2179,40 @@ sig2name(int sig) } static void -session_close_x11(int id) +session_close_x11(struct ssh *ssh, int id) { Channel *c; - if ((c = channel_by_id(id)) == NULL) { - debug("session_close_x11: x11 channel %d missing", id); + if ((c = channel_by_id(ssh, id)) == NULL) { + debug("%s: x11 channel %d missing", __func__, id); } else { /* Detach X11 listener */ - debug("session_close_x11: detach x11 channel %d", id); - channel_cancel_cleanup(id); + debug("%s: detach x11 channel %d", __func__, id); + channel_cancel_cleanup(ssh, id); if (c->ostate != CHAN_OUTPUT_CLOSED) - chan_mark_dead(c); + chan_mark_dead(ssh, c); } } static void -session_close_single_x11(int id, void *arg) +session_close_single_x11(struct ssh *ssh, int id, void *arg) { Session *s; u_int i; - debug3("session_close_single_x11: channel %d", id); - channel_cancel_cleanup(id); + debug3("%s: channel %d", __func__, id); + channel_cancel_cleanup(ssh, id); if ((s = session_by_x11_channel(id)) == NULL) - fatal("session_close_single_x11: no x11 channel %d", id); + fatal("%s: no x11 channel %d", __func__, id); for (i = 0; s->x11_chanids[i] != -1; i++) { - debug("session_close_single_x11: session %d: " - "closing channel %d", s->self, s->x11_chanids[i]); + debug("%s: session %d: closing channel %d", + __func__, s->self, s->x11_chanids[i]); /* * The channel "id" is already closing, but make sure we * close all of its siblings. */ if (s->x11_chanids[i] != id) - session_close_x11(s->x11_chanids[i]); + session_close_x11(ssh, s->x11_chanids[i]); } free(s->x11_chanids); s->x11_chanids = NULL; @@ -2240,22 +2227,22 @@ session_close_single_x11(int id, void *arg) } static void -session_exit_message(Session *s, int status) +session_exit_message(struct ssh *ssh, Session *s, int status) { Channel *c; - if ((c = channel_lookup(s->chanid)) == NULL) - fatal("session_exit_message: session %d: no channel %d", - s->self, s->chanid); - debug("session_exit_message: session %d channel %d pid %ld", - s->self, s->chanid, (long)s->pid); + if ((c = channel_lookup(ssh, s->chanid)) == NULL) + fatal("%s: session %d: no channel %d", + __func__, s->self, s->chanid); + debug("%s: session %d channel %d pid %ld", + __func__, s->self, s->chanid, (long)s->pid); if (WIFEXITED(status)) { - channel_request_start(s->chanid, "exit-status", 0); + channel_request_start(ssh, s->chanid, "exit-status", 0); packet_put_int(WEXITSTATUS(status)); packet_send(); } else if (WIFSIGNALED(status)) { - channel_request_start(s->chanid, "exit-signal", 0); + channel_request_start(ssh, s->chanid, "exit-signal", 0); packet_put_cstring(sig2name(WTERMSIG(status))); #ifdef WCOREDUMP packet_put_char(WCOREDUMP(status)? 1 : 0); @@ -2271,14 +2258,14 @@ session_exit_message(Session *s, int status) } /* disconnect channel */ - debug("session_exit_message: release channel %d", s->chanid); + debug("%s: release channel %d", __func__, s->chanid); /* * Adjust cleanup callback attachment to send close messages when * the channel gets EOF. The session will be then be closed * by session_close_by_channel when the childs close their fds. */ - channel_register_cleanup(c->self, session_close_by_channel, 1); + channel_register_cleanup(ssh, c->self, session_close_by_channel, 1); /* * emulate a write failure with 'chan_write_failed', nobody will be @@ -2287,13 +2274,12 @@ session_exit_message(Session *s, int status) * be some more data waiting in the pipe. */ if (c->ostate != CHAN_OUTPUT_CLOSED) - chan_write_failed(c); + chan_write_failed(ssh, c); } void -session_close(Session *s) +session_close(struct ssh *ssh, Session *s) { - struct ssh *ssh = active_state; /* XXX */ u_int i; verbose("Close session: user %s from %.200s port %d id %d", @@ -2323,16 +2309,15 @@ session_close(Session *s) } void -session_close_by_pid(pid_t pid, int status) +session_close_by_pid(struct ssh *ssh, pid_t pid, int status) { Session *s = session_by_pid(pid); if (s == NULL) { - debug("session_close_by_pid: no session for pid %ld", - (long)pid); + debug("%s: no session for pid %ld", __func__, (long)pid); return; } if (s->chanid != -1) - session_exit_message(s, status); + session_exit_message(ssh, s, status); if (s->ttyfd != -1) session_pty_cleanup(s); s->pid = 0; @@ -2343,19 +2328,18 @@ session_close_by_pid(pid_t pid, int status) * the session 'child' itself dies */ void -session_close_by_channel(int id, void *arg) +session_close_by_channel(struct ssh *ssh, int id, void *arg) { Session *s = session_by_channel(id); u_int i; if (s == NULL) { - debug("session_close_by_channel: no session for id %d", id); + debug("%s: no session for id %d", __func__, id); return; } - debug("session_close_by_channel: channel %d child %ld", - id, (long)s->pid); + debug("%s: channel %d child %ld", __func__, id, (long)s->pid); if (s->pid != 0) { - debug("session_close_by_channel: channel %d: has child", id); + debug("%s: channel %d: has child", __func__, id); /* * delay detach of session, but release pty, since * the fd's to the child are already closed @@ -2365,22 +2349,22 @@ session_close_by_channel(int id, void *arg) return; } /* detach by removing callback */ - channel_cancel_cleanup(s->chanid); + channel_cancel_cleanup(ssh, s->chanid); /* Close any X11 listeners associated with this session */ if (s->x11_chanids != NULL) { for (i = 0; s->x11_chanids[i] != -1; i++) { - session_close_x11(s->x11_chanids[i]); + session_close_x11(ssh, s->x11_chanids[i]); s->x11_chanids[i] = -1; } } s->chanid = -1; - session_close(s); + session_close(ssh, s); } void -session_destroy_all(void (*closefunc)(Session *)) +session_destroy_all(struct ssh *ssh, void (*closefunc)(Session *)) { int i; for (i = 0; i < sessions_nalloc; i++) { @@ -2389,7 +2373,7 @@ session_destroy_all(void (*closefunc)(Session *)) if (closefunc != NULL) closefunc(s); else - session_close(s); + session_close(ssh, s); } } } @@ -2432,7 +2416,7 @@ session_proctitle(Session *s) } int -session_setup_x11fwd(Session *s) +session_setup_x11fwd(struct ssh *ssh, Session *s) { struct stat st; char display[512], auth_display[512]; @@ -2456,14 +2440,14 @@ session_setup_x11fwd(Session *s) debug("X11 display already set."); return 0; } - if (x11_create_display_inet(options.x11_display_offset, + if (x11_create_display_inet(ssh, options.x11_display_offset, options.x11_use_localhost, s->single_connection, &s->display_number, &s->x11_chanids) == -1) { debug("x11_create_display_inet failed."); return 0; } for (i = 0; s->x11_chanids[i] != -1; i++) { - channel_register_cleanup(s->x11_chanids[i], + channel_register_cleanup(ssh, s->x11_chanids[i], session_close_single_x11, 0); } @@ -2508,13 +2492,13 @@ session_setup_x11fwd(Session *s) } static void -do_authenticated2(Authctxt *authctxt) +do_authenticated2(struct ssh *ssh, Authctxt *authctxt) { - server_loop2(authctxt); + server_loop2(ssh, authctxt); } void -do_cleanup(Authctxt *authctxt) +do_cleanup(struct ssh *ssh, Authctxt *authctxt) { static int called = 0; @@ -2556,12 +2540,21 @@ do_cleanup(Authctxt *authctxt) /* remove agent socket */ auth_sock_cleanup_proc(authctxt->pw); + /* remove userauth info */ + if (auth_info_file != NULL) { + temporarily_use_uid(authctxt->pw); + unlink(auth_info_file); + restore_uid(); + free(auth_info_file); + auth_info_file = NULL; + } + /* * Cleanup ptys/utmp only if privsep is disabled, * or if running in monitor. */ if (!use_privsep || mm_is_monitor()) - session_destroy_all(session_pty_cleanup2); + session_destroy_all(ssh, session_pty_cleanup2); } /* Return a name for the remote host that fits inside utmp_size */ diff --git a/session.h b/session.h index 98e1dafee2b8..54dd1f0ca081 100644 --- a/session.h +++ b/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.33 2016/08/13 17:47:41 markus Exp $ */ +/* $OpenBSD: session.h,v 1.35 2017/09/12 06:32:07 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -62,23 +62,21 @@ struct Session { } *env; }; -void do_authenticated(Authctxt *); -void do_cleanup(Authctxt *); +void do_authenticated(struct ssh *, Authctxt *); +void do_cleanup(struct ssh *, Authctxt *); int session_open(Authctxt *, int); void session_unused(int); -int session_input_channel_req(Channel *, const char *); -void session_close_by_pid(pid_t, int); -void session_close_by_channel(int, void *); -void session_destroy_all(void (*)(Session *)); +int session_input_channel_req(struct ssh *, Channel *, const char *); +void session_close_by_pid(struct ssh *ssh, pid_t, int); +void session_close_by_channel(struct ssh *, int, void *); +void session_destroy_all(struct ssh *, void (*)(Session *)); void session_pty_cleanup2(Session *); Session *session_new(void); Session *session_by_tty(char *); -void session_close(Session *); +void session_close(struct ssh *, Session *); void do_setusercontext(struct passwd *); -void child_set_env(char ***envp, u_int *envsizep, const char *name, - const char *value); const char *session_get_remote_name_or_ip(struct ssh *, u_int, int); diff --git a/sftp-client.c b/sftp-client.c index a6e832270410..626330262264 100644 --- a/sftp-client.c +++ b/sftp-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-client.c,v 1.126 2017/01/03 05:46:51 djm Exp $ */ +/* $OpenBSD: sftp-client.c,v 1.127 2017/08/11 04:41:08 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -140,7 +140,7 @@ get_msg(struct sftp_conn *conn, struct sshbuf *m) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (atomicio6(read, conn->fd_in, p, 4, conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) { - if (errno == EPIPE) + if (errno == EPIPE || errno == ECONNRESET) fatal("Connection closed"); else fatal("Couldn't read packet: %s", strerror(errno)); diff --git a/sftp-common.c b/sftp-common.c index 3a70c52dd3dd..13a7f5becc24 100644 --- a/sftp-common.c +++ b/sftp-common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-common.c,v 1.29 2016/09/12 01:22:38 deraadt Exp $ */ +/* $OpenBSD: sftp-common.c,v 1.30 2017/06/10 06:36:46 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Damien Miller. All rights reserved. @@ -216,22 +216,21 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units) int ulen, glen, sz = 0; struct tm *ltime = localtime(&st->st_mtime); char *user, *group; - char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1]; + char buf[1024], lc[8], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1]; char sbuf[FMT_SCALED_STRSIZE]; time_t now; strmode(st->st_mode, mode); - if (!remote) { - user = user_from_uid(st->st_uid, 0); - } else { + if (remote) { snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid); user = ubuf; - } - if (!remote) { - group = group_from_gid(st->st_gid, 0); - } else { snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid); group = gbuf; + strlcpy(lc, "?", sizeof(lc)); + } else { + user = user_from_uid(st->st_uid, 0); + group = group_from_gid(st->st_gid, 0); + snprintf(lc, sizeof(lc), "%u", (u_int)st->st_nlink); } if (ltime != NULL) { now = time(NULL); @@ -247,12 +246,12 @@ ls_file(const char *name, const struct stat *st, int remote, int si_units) glen = MAXIMUM(strlen(group), 8); if (si_units) { fmt_scaled((long long)st->st_size, sbuf); - snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8s %s %s", mode, - (u_int)st->st_nlink, ulen, user, glen, group, + snprintf(buf, sizeof buf, "%s %3s %-*s %-*s %8s %s %s", + mode, lc, ulen, user, glen, group, sbuf, tbuf, name); } else { - snprintf(buf, sizeof buf, "%s %3u %-*s %-*s %8llu %s %s", mode, - (u_int)st->st_nlink, ulen, user, glen, group, + snprintf(buf, sizeof buf, "%s %3s %-*s %-*s %8llu %s %s", + mode, lc, ulen, user, glen, group, (unsigned long long)st->st_size, tbuf, name); } return xstrdup(buf); diff --git a/sftp-server.0 b/sftp-server.0 index 20d477d49562..4f994f4c595f 100644 --- a/sftp-server.0 +++ b/sftp-server.0 @@ -93,4 +93,4 @@ HISTORY AUTHORS Markus Friedl -OpenBSD 6.0 December 11, 2014 OpenBSD 6.0 +OpenBSD 6.2 December 11, 2014 OpenBSD 6.2 diff --git a/sftp-server.c b/sftp-server.c index 3619cdfc0ffe..df0fb50680fe 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-server.c,v 1.110 2016/09/12 01:22:38 deraadt Exp $ */ +/* $OpenBSD: sftp-server.c,v 1.111 2017/04/04 00:24:56 djm Exp $ */ /* * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. * @@ -691,8 +691,8 @@ process_open(u_int32_t id) logit("open \"%s\" flags %s mode 0%o", name, string_from_portable(pflags), mode); if (readonly && - ((flags & O_ACCMODE) == O_WRONLY || - (flags & O_ACCMODE) == O_RDWR)) { + ((flags & O_ACCMODE) != O_RDONLY || + (flags & (O_CREAT|O_TRUNC)) != 0)) { verbose("Refusing open request in read-only mode"); status = SSH2_FX_PERMISSION_DENIED; } else { diff --git a/sftp.0 b/sftp.0 index 2e0c274d9f6f..45b8faf5543d 100644 --- a/sftp.0 +++ b/sftp.0 @@ -4,7 +4,7 @@ NAME sftp M-bM-^@M-^S secure file transfer program SYNOPSIS - sftp [-1246aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher] + sftp [-46aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher] [-D sftp_server_path] [-F ssh_config] [-i identity_file] [-l limit] [-o ssh_option] [-P port] [-R num_requests] [-S program] [-s subsystem | sftp_server] host @@ -36,10 +36,6 @@ DESCRIPTION The options are as follows: - -1 Specify the use of protocol version 1. - - -2 Specify the use of protocol version 2. - -4 Forces sftp to use IPv4 addresses only. -6 Forces sftp to use IPv6 addresses only. @@ -111,10 +107,8 @@ DESCRIPTION CertificateFile ChallengeResponseAuthentication CheckHostIP - Cipher Ciphers Compression - CompressionLevel ConnectionAttempts ConnectTimeout ControlMaster @@ -145,13 +139,11 @@ DESCRIPTION PKCS11Provider Port PreferredAuthentications - Protocol ProxyCommand ProxyJump + PubkeyAcceptedKeyTypes PubkeyAuthentication RekeyLimit - RhostsRSAAuthentication - RSAAuthentication SendEnv ServerAliveInterval ServerAliveCountMax @@ -187,9 +179,8 @@ DESCRIPTION -s subsystem | sftp_server Specifies the SSH2 subsystem or the path for an sftp server on - the remote host. A path is useful for using sftp over protocol - version 1, or when the remote sshd(8) does not have an sftp - subsystem configured. + the remote host. A path is useful when the remote sshd(8) does + not have an sftp subsystem configured. -v Raise logging level. This option is also passed to ssh. @@ -383,4 +374,4 @@ SEE ALSO T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh- filexfer-00.txt, January 2001, work in progress material. -OpenBSD 6.0 July 16, 2016 OpenBSD 6.0 +OpenBSD 6.2 May 3, 2017 OpenBSD 6.2 diff --git a/sftp.1 b/sftp.1 index fbdd00a1efd1..c218376fbf0c 100644 --- a/sftp.1 +++ b/sftp.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sftp.1,v 1.105 2016/07/16 06:57:55 jmc Exp $ +.\" $OpenBSD: sftp.1,v 1.110 2017/05/03 21:49:18 naddy Exp $ .\" .\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" @@ -22,7 +22,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: July 16 2016 $ +.Dd $Mdocdate: May 3 2017 $ .Dt SFTP 1 .Os .Sh NAME @@ -31,7 +31,7 @@ .Sh SYNOPSIS .Nm sftp .Bk -words -.Op Fl 1246aCfpqrv +.Op Fl 46aCfpqrv .Op Fl B Ar buffer_size .Op Fl b Ar batchfile .Op Fl c Ar cipher @@ -95,10 +95,6 @@ names, IPv6 addresses must be enclosed in square brackets to avoid ambiguity. .Pp The options are as follows: .Bl -tag -width Ds -.It Fl 1 -Specify the use of protocol version 1. -.It Fl 2 -Specify the use of protocol version 2. .It Fl 4 Forces .Nm @@ -201,10 +197,8 @@ For full details of the options listed below, and their possible values, see .It CertificateFile .It ChallengeResponseAuthentication .It CheckHostIP -.It Cipher .It Ciphers .It Compression -.It CompressionLevel .It ConnectionAttempts .It ConnectTimeout .It ControlMaster @@ -235,13 +229,11 @@ For full details of the options listed below, and their possible values, see .It PKCS11Provider .It Port .It PreferredAuthentications -.It Protocol .It ProxyCommand .It ProxyJump +.It PubkeyAcceptedKeyTypes .It PubkeyAuthentication .It RekeyLimit -.It RhostsRSAAuthentication -.It RSAAuthentication .It SendEnv .It ServerAliveInterval .It ServerAliveCountMax @@ -282,9 +274,7 @@ options. .It Fl s Ar subsystem | sftp_server Specifies the SSH2 subsystem or the path for an sftp server on the remote host. -A path is useful for using -.Nm -over protocol version 1, or when the remote +A path is useful when the remote .Xr sshd 8 does not have an sftp subsystem configured. .It Fl v diff --git a/sftp.c b/sftp.c index 76add3908ca7..67110f738f79 100644 --- a/sftp.c +++ b/sftp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp.c,v 1.178 2017/02/15 01:46:47 djm Exp $ */ +/* $OpenBSD: sftp.c,v 1.180 2017/06/10 06:33:34 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -106,6 +106,7 @@ volatile sig_atomic_t interrupted = 0; /* I wish qsort() took a separate ctx for the comparison function...*/ int sort_flag; +glob_t *sort_glob; /* Context used for commandline completion */ struct complete_ctx { @@ -879,6 +880,34 @@ do_ls_dir(struct sftp_conn *conn, const char *path, return (0); } +static int +sglob_comp(const void *aa, const void *bb) +{ + u_int a = *(const u_int *)aa; + u_int b = *(const u_int *)bb; + const char *ap = sort_glob->gl_pathv[a]; + const char *bp = sort_glob->gl_pathv[b]; + const struct stat *as = sort_glob->gl_statv[a]; + const struct stat *bs = sort_glob->gl_statv[b]; + int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1; + +#define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1)) + if (sort_flag & LS_NAME_SORT) + return (rmul * strcmp(ap, bp)); + else if (sort_flag & LS_TIME_SORT) { +#if defined(HAVE_STRUCT_STAT_ST_MTIM) + return (rmul * timespeccmp(&as->st_mtim, &bs->st_mtim, <)); +#elif defined(HAVE_STRUCT_STAT_ST_MTIME) + return (rmul * NCMP(as->st_mtime, bs->st_mtime)); +#else + return rmul * 1; +#endif + } else if (sort_flag & LS_SIZE_SORT) + return (rmul * NCMP(as->st_size, bs->st_size)); + + fatal("Unknown ls sort type"); +} + /* sftp ls.1 replacement which handles path globs */ static int do_globbed_ls(struct sftp_conn *conn, const char *path, @@ -888,7 +917,8 @@ do_globbed_ls(struct sftp_conn *conn, const char *path, glob_t g; int err, r; struct winsize ws; - u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80; + u_int i, j, nentries, *indices = NULL, c = 1; + u_int colspace = 0, columns = 1, m = 0, width = 80; memset(&g, 0, sizeof(g)); @@ -933,7 +963,26 @@ do_globbed_ls(struct sftp_conn *conn, const char *path, colspace = width / columns; } - for (i = 0; g.gl_pathv[i] && !interrupted; i++) { + /* + * Sorting: rather than mess with the contents of glob_t, prepare + * an array of indices into it and sort that. For the usual + * unsorted case, the indices are just the identity 1=1, 2=2, etc. + */ + for (nentries = 0; g.gl_pathv[nentries] != NULL; nentries++) + ; /* count entries */ + indices = calloc(nentries, sizeof(*indices)); + for (i = 0; i < nentries; i++) + indices[i] = i; + + if (lflag & SORT_FLAGS) { + sort_glob = &g; + sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT); + qsort(indices, nentries, sizeof(*indices), sglob_comp); + sort_glob = NULL; + } + + for (j = 0; j < nentries && !interrupted; j++) { + i = indices[j]; fname = path_strip(g.gl_pathv[i], strip_path); if (lflag & LS_LONG_VIEW) { if (g.gl_statv[i] == NULL) { @@ -961,6 +1010,7 @@ do_globbed_ls(struct sftp_conn *conn, const char *path, out: if (g.gl_pathc) globfree(&g); + free(indices); return 0; } @@ -2246,7 +2296,7 @@ usage(void) extern char *__progname; fprintf(stderr, - "usage: %s [-1246aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n" + "usage: %s [-46aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n" " [-D sftp_server_path] [-F ssh_config] " "[-i identity_file] [-l limit]\n" " [-o ssh_option] [-P port] [-R num_requests] " diff --git a/ssh-add.0 b/ssh-add.0 index 706bfe661027..2ef6c3da298d 100644 --- a/ssh-add.0 +++ b/ssh-add.0 @@ -4,18 +4,18 @@ NAME ssh-add M-bM-^@M-^S adds private key identities to the authentication agent SYNOPSIS - ssh-add [-cDdkLlXx] [-E fingerprint_hash] [-t life] [file ...] + ssh-add [-cDdkLlqXx] [-E fingerprint_hash] [-t life] [file ...] ssh-add -s pkcs11 ssh-add -e pkcs11 DESCRIPTION ssh-add adds private key identities to the authentication agent, ssh-agent(1). When run without arguments, it adds the files - ~/.ssh/id_rsa, ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and - ~/.ssh/identity. After loading a private key, ssh-add will try to load - corresponding certificate information from the filename obtained by - appending -cert.pub to the name of the private key file. Alternative - file names can be given on the command line. + ~/.ssh/id_rsa, ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, and ~/.ssh/id_ed25519. + After loading a private key, ssh-add will try to load corresponding + certificate information from the filename obtained by appending -cert.pub + to the name of the private key file. Alternative file names can be given + on the command line. If any file requires a passphrase, ssh-add asks for the passphrase from the user. The passphrase is read from the user's tty. ssh-add retries @@ -60,6 +60,8 @@ DESCRIPTION -l Lists fingerprints of all identities currently represented by the agent. + -q Be quiet after a successful operation. + -s pkcs11 Add keys provided by the PKCS#11 shared library pkcs11. @@ -89,25 +91,17 @@ ENVIRONMENT with the agent. FILES - ~/.ssh/identity - Contains the protocol version 1 RSA authentication identity of - the user. - ~/.ssh/id_dsa - Contains the protocol version 2 DSA authentication identity of - the user. + Contains the DSA authentication identity of the user. ~/.ssh/id_ecdsa - Contains the protocol version 2 ECDSA authentication identity of - the user. + Contains the ECDSA authentication identity of the user. ~/.ssh/id_ed25519 - Contains the protocol version 2 Ed25519 authentication identity - of the user. + Contains the Ed25519 authentication identity of the user. ~/.ssh/id_rsa - Contains the protocol version 2 RSA authentication identity of - the user. + Contains the RSA authentication identity of the user. Identity files should not be readable by anyone but the user. Note that ssh-add ignores identity files if they are accessible by others. @@ -126,4 +120,4 @@ AUTHORS created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. -OpenBSD 6.0 March 30, 2015 OpenBSD 6.0 +OpenBSD 6.2 August 29, 2017 OpenBSD 6.2 diff --git a/ssh-add.1 b/ssh-add.1 index f02b595d51e5..d5da9279c5f9 100644 --- a/ssh-add.1 +++ b/ssh-add.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-add.1,v 1.62 2015/03/30 18:28:37 jmc Exp $ +.\" $OpenBSD: ssh-add.1,v 1.66 2017/08/29 13:05:58 jmc Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: March 30 2015 $ +.Dd $Mdocdate: August 29 2017 $ .Dt SSH-ADD 1 .Os .Sh NAME @@ -43,7 +43,7 @@ .Nd adds private key identities to the authentication agent .Sh SYNOPSIS .Nm ssh-add -.Op Fl cDdkLlXx +.Op Fl cDdkLlqXx .Op Fl E Ar fingerprint_hash .Op Fl t Ar life .Op Ar @@ -59,9 +59,8 @@ When run without arguments, it adds the files .Pa ~/.ssh/id_rsa , .Pa ~/.ssh/id_dsa , .Pa ~/.ssh/id_ecdsa , -.Pa ~/.ssh/id_ed25519 and -.Pa ~/.ssh/identity . +.Pa ~/.ssh/id_ed25519 . After loading a private key, .Nm will try to load corresponding certificate information from the @@ -127,6 +126,8 @@ Lists public key parameters of all identities currently represented by the agent. .It Fl l Lists fingerprints of all identities currently represented by the agent. +.It Fl q +Be quiet after a successful operation. .It Fl s Ar pkcs11 Add keys provided by the PKCS#11 shared library .Ar pkcs11 . @@ -174,16 +175,14 @@ socket used to communicate with the agent. .El .Sh FILES .Bl -tag -width Ds -.It Pa ~/.ssh/identity -Contains the protocol version 1 RSA authentication identity of the user. .It Pa ~/.ssh/id_dsa -Contains the protocol version 2 DSA authentication identity of the user. +Contains the DSA authentication identity of the user. .It Pa ~/.ssh/id_ecdsa -Contains the protocol version 2 ECDSA authentication identity of the user. +Contains the ECDSA authentication identity of the user. .It Pa ~/.ssh/id_ed25519 -Contains the protocol version 2 Ed25519 authentication identity of the user. +Contains the Ed25519 authentication identity of the user. .It Pa ~/.ssh/id_rsa -Contains the protocol version 2 RSA authentication identity of the user. +Contains the RSA authentication identity of the user. .El .Pp Identity files should not be readable by anyone but the user. diff --git a/ssh-add.c b/ssh-add.c index fb9a53e64cfe..2afd483305cc 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-add.c,v 1.128 2016/02/15 09:47:49 dtucker Exp $ */ +/* $OpenBSD: ssh-add.c,v 1.134 2017/08/29 09:42:29 dlg Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -55,7 +55,6 @@ #include "xmalloc.h" #include "ssh.h" -#include "rsa.h" #include "log.h" #include "sshkey.h" #include "sshbuf.h" @@ -79,9 +78,6 @@ static char *default_files[] = { #endif #endif /* WITH_OPENSSL */ _PATH_SSH_CLIENT_ID_ED25519, -#ifdef WITH_SSH1 - _PATH_SSH_CLIENT_IDENTITY, -#endif NULL }; @@ -106,7 +102,7 @@ clear_pass(void) } static int -delete_file(int agent_fd, const char *filename, int key_only) +delete_file(int agent_fd, const char *filename, int key_only, int qflag) { struct sshkey *public, *cert = NULL; char *certpath = NULL, *comment = NULL; @@ -117,7 +113,10 @@ delete_file(int agent_fd, const char *filename, int key_only) return -1; } if ((r = ssh_remove_identity(agent_fd, public)) == 0) { - fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment); + if (!qflag) { + fprintf(stderr, "Identity removed: %s (%s)\n", + filename, comment); + } ret = 0; } else fprintf(stderr, "Could not remove identity \"%s\": %s\n", @@ -142,8 +141,10 @@ delete_file(int agent_fd, const char *filename, int key_only) certpath, filename); if ((r = ssh_remove_identity(agent_fd, cert)) == 0) { - fprintf(stderr, "Identity removed: %s (%s)\n", certpath, - comment); + if (!qflag) { + fprintf(stderr, "Identity removed: %s (%s)\n", + certpath, comment); + } ret = 0; } else fprintf(stderr, "Could not remove identity \"%s\": %s\n", @@ -164,6 +165,11 @@ delete_all(int agent_fd) { int ret = -1; + /* + * Since the agent might be forwarded, old or non-OpenSSH, when asked + * to remove all keys, attempt to remove both protocol v.1 and v.2 + * keys. + */ if (ssh_remove_all_identities(agent_fd, 2) == 0) ret = 0; /* ignore error-code for ssh1 */ @@ -178,7 +184,7 @@ delete_all(int agent_fd) } static int -add_file(int agent_fd, const char *filename, int key_only) +add_file(int agent_fd, const char *filename, int key_only, int qflag) { struct sshkey *private, *cert; char *comment = NULL; @@ -304,7 +310,7 @@ add_file(int agent_fd, const char *filename, int key_only) goto out; } if ((r = sshkey_cert_copy(cert, private)) != 0) { - error("%s: key_cert_copy: %s", __func__, ssh_err(r)); + error("%s: sshkey_cert_copy: %s", __func__, ssh_err(r)); sshkey_free(cert); goto out; } @@ -360,50 +366,36 @@ static int list_identities(int agent_fd, int do_fp) { char *fp; - int r, had_identities = 0; + int r; struct ssh_identitylist *idlist; size_t i; -#ifdef WITH_SSH1 - int version = 1; -#else - int version = 2; -#endif - for (; version <= 2; version++) { - if ((r = ssh_fetch_identitylist(agent_fd, version, - &idlist)) != 0) { - if (r != SSH_ERR_AGENT_NO_IDENTITIES) - fprintf(stderr, "error fetching identities for " - "protocol %d: %s\n", version, ssh_err(r)); - continue; - } - for (i = 0; i < idlist->nkeys; i++) { - had_identities = 1; - if (do_fp) { - fp = sshkey_fingerprint(idlist->keys[i], - fingerprint_hash, SSH_FP_DEFAULT); - printf("%u %s %s (%s)\n", - sshkey_size(idlist->keys[i]), - fp == NULL ? "(null)" : fp, - idlist->comments[i], - sshkey_type(idlist->keys[i])); - free(fp); - } else { - if ((r = sshkey_write(idlist->keys[i], - stdout)) != 0) { - fprintf(stderr, "sshkey_write: %s\n", - ssh_err(r)); - continue; - } - fprintf(stdout, " %s\n", idlist->comments[i]); - } - } - ssh_free_identitylist(idlist); - } - if (!had_identities) { - printf("The agent has no identities.\n"); + if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) { + if (r != SSH_ERR_AGENT_NO_IDENTITIES) + fprintf(stderr, "error fetching identities: %s\n", + ssh_err(r)); + else + printf("The agent has no identities.\n"); return -1; } + for (i = 0; i < idlist->nkeys; i++) { + if (do_fp) { + fp = sshkey_fingerprint(idlist->keys[i], + fingerprint_hash, SSH_FP_DEFAULT); + printf("%u %s %s (%s)\n", sshkey_size(idlist->keys[i]), + fp == NULL ? "(null)" : fp, idlist->comments[i], + sshkey_type(idlist->keys[i])); + free(fp); + } else { + if ((r = sshkey_write(idlist->keys[i], stdout)) != 0) { + fprintf(stderr, "sshkey_write: %s\n", + ssh_err(r)); + continue; + } + fprintf(stdout, " %s\n", idlist->comments[i]); + } + } + ssh_free_identitylist(idlist); return 0; } @@ -440,13 +432,13 @@ lock_agent(int agent_fd, int lock) } static int -do_file(int agent_fd, int deleting, int key_only, char *file) +do_file(int agent_fd, int deleting, int key_only, char *file, int qflag) { if (deleting) { - if (delete_file(agent_fd, file, key_only) == -1) + if (delete_file(agent_fd, file, key_only, qflag) == -1) return -1; } else { - if (add_file(agent_fd, file, key_only) == -1) + if (add_file(agent_fd, file, key_only, qflag) == -1) return -1; } return 0; @@ -469,6 +461,7 @@ usage(void) fprintf(stderr, " -X Unlock agent.\n"); fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n"); fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n"); + fprintf(stderr, " -q Be quiet after a successful operation.\n"); } int @@ -479,7 +472,7 @@ main(int argc, char **argv) int agent_fd; char *pkcs11provider = NULL; int r, i, ch, deleting = 0, ret = 0, key_only = 0; - int xflag = 0, lflag = 0, Dflag = 0; + int xflag = 0, lflag = 0, Dflag = 0, qflag = 0; ssh_malloc_init(); /* must be called before any mallocs */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ @@ -507,7 +500,7 @@ main(int argc, char **argv) exit(2); } - while ((ch = getopt(argc, argv, "klLcdDxXE:e:s:t:")) != -1) { + while ((ch = getopt(argc, argv, "klLcdDxXE:e:qs:t:")) != -1) { switch (ch) { case 'E': fingerprint_hash = ssh_digest_alg_by_name(optarg); @@ -552,6 +545,9 @@ main(int argc, char **argv) goto done; } break; + case 'q': + qflag = 1; + break; default: usage(); ret = 1; @@ -600,7 +596,8 @@ main(int argc, char **argv) default_files[i]); if (stat(buf, &st) < 0) continue; - if (do_file(agent_fd, deleting, key_only, buf) == -1) + if (do_file(agent_fd, deleting, key_only, buf, + qflag) == -1) ret = 1; else count++; @@ -610,7 +607,7 @@ main(int argc, char **argv) } else { for (i = 0; i < argc; i++) { if (do_file(agent_fd, deleting, key_only, - argv[i]) == -1) + argv[i], qflag) == -1) ret = 1; } } diff --git a/ssh-agent.0 b/ssh-agent.0 index bb3c8d6055fa..86ac988bdf1a 100644 --- a/ssh-agent.0 +++ b/ssh-agent.0 @@ -117,4 +117,4 @@ AUTHORS created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. -OpenBSD 6.0 November 30, 2016 OpenBSD 6.0 +OpenBSD 6.2 November 30, 2016 OpenBSD 6.2 diff --git a/ssh-agent.c b/ssh-agent.c index b987562b9aa1..0c6c3659217f 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.218 2017/03/15 03:52:30 deraadt Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.224 2017/07/24 04:34:28 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -60,6 +60,9 @@ #ifdef HAVE_PATHS_H # include #endif +#ifdef HAVE_POLL_H +# include +#endif #include #include #include @@ -73,7 +76,6 @@ #include "xmalloc.h" #include "ssh.h" -#include "rsa.h" #include "sshbuf.h" #include "sshkey.h" #include "authfd.h" @@ -92,6 +94,9 @@ # define DEFAULT_PKCS11_WHITELIST "/usr/lib*/*,/usr/local/lib*/*" #endif +/* Maximum accepted message length */ +#define AGENT_MAX_LEN (256*1024) + typedef enum { AUTH_UNUSED, AUTH_SOCKET, @@ -118,13 +123,13 @@ typedef struct identity { u_int confirm; } Identity; -typedef struct { +struct idtable { int nentries; TAILQ_HEAD(idqueue, identity) idlist; -} Idtab; +}; -/* private key table, one per protocol version */ -Idtab idtable[3]; +/* private key table */ +struct idtable *idtab; int max_fd = 0; @@ -171,21 +176,9 @@ close_socket(SocketEntry *e) static void idtab_init(void) { - int i; - - for (i = 0; i <=2; i++) { - TAILQ_INIT(&idtable[i].idlist); - idtable[i].nentries = 0; - } -} - -/* return private key table for requested protocol version */ -static Idtab * -idtab_lookup(int version) -{ - if (version < 1 || version > 2) - fatal("internal error, bad protocol version %d", version); - return &idtable[version]; + idtab = xcalloc(1, sizeof(*idtab)); + TAILQ_INIT(&idtab->idlist); + idtab->nentries = 0; } static void @@ -199,12 +192,11 @@ free_identity(Identity *id) /* return matching private key for given public key */ static Identity * -lookup_identity(struct sshkey *key, int version) +lookup_identity(struct sshkey *key) { Identity *id; - Idtab *tab = idtab_lookup(version); - TAILQ_FOREACH(id, &tab->idlist, next) { + TAILQ_FOREACH(id, &idtab->idlist, next) { if (sshkey_equal(key, id->key)) return (id); } @@ -241,135 +233,30 @@ send_status(SocketEntry *e, int success) /* send list of supported public keys to 'client' */ static void -process_request_identities(SocketEntry *e, int version) +process_request_identities(SocketEntry *e) { - Idtab *tab = idtab_lookup(version); Identity *id; struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); - if ((r = sshbuf_put_u8(msg, (version == 1) ? - SSH_AGENT_RSA_IDENTITIES_ANSWER : - SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || - (r = sshbuf_put_u32(msg, tab->nentries)) != 0) + if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || + (r = sshbuf_put_u32(msg, idtab->nentries)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); - TAILQ_FOREACH(id, &tab->idlist, next) { - if (id->key->type == KEY_RSA1) { -#ifdef WITH_SSH1 - if ((r = sshbuf_put_u32(msg, - BN_num_bits(id->key->rsa->n))) != 0 || - (r = sshbuf_put_bignum1(msg, - id->key->rsa->e)) != 0 || - (r = sshbuf_put_bignum1(msg, - id->key->rsa->n)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); -#endif - } else { - u_char *blob; - size_t blen; - - if ((r = sshkey_to_blob(id->key, &blob, &blen)) != 0) { - error("%s: sshkey_to_blob: %s", __func__, - ssh_err(r)); - continue; - } - if ((r = sshbuf_put_string(msg, blob, blen)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); - free(blob); - } - if ((r = sshbuf_put_cstring(msg, id->comment)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - } - if ((r = sshbuf_put_stringb(e->output, msg)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - sshbuf_free(msg); -} - -#ifdef WITH_SSH1 -/* ssh1 only */ -static void -process_authentication_challenge1(SocketEntry *e) -{ - u_char buf[32], mdbuf[16], session_id[16]; - u_int response_type; - BIGNUM *challenge; - Identity *id; - int r, len; - struct sshbuf *msg; - struct ssh_digest_ctx *md; - struct sshkey *key; - - if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); - if ((key = sshkey_new(KEY_RSA1)) == NULL) - fatal("%s: sshkey_new failed", __func__); - if ((challenge = BN_new()) == NULL) - fatal("%s: BN_new failed", __func__); - - if ((r = sshbuf_get_u32(e->request, NULL)) != 0 || /* ignored */ - (r = sshbuf_get_bignum1(e->request, key->rsa->e)) != 0 || - (r = sshbuf_get_bignum1(e->request, key->rsa->n)) != 0 || - (r = sshbuf_get_bignum1(e->request, challenge))) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - - /* Only protocol 1.1 is supported */ - if (sshbuf_len(e->request) == 0) - goto failure; - if ((r = sshbuf_get(e->request, session_id, sizeof(session_id))) != 0 || - (r = sshbuf_get_u32(e->request, &response_type)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - if (response_type != 1) - goto failure; - - id = lookup_identity(key, 1); - if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { - struct sshkey *private = id->key; - /* Decrypt the challenge using the private key. */ - if ((r = rsa_private_decrypt(challenge, challenge, - private->rsa) != 0)) { - fatal("%s: rsa_public_encrypt: %s", __func__, + TAILQ_FOREACH(id, &idtab->idlist, next) { + if ((r = sshkey_puts(id->key, msg)) != 0 || + (r = sshbuf_put_cstring(msg, id->comment)) != 0) { + error("%s: put key/comment: %s", __func__, ssh_err(r)); - goto failure; /* XXX ? */ + continue; } - - /* The response is MD5 of decrypted challenge plus session id */ - len = BN_num_bytes(challenge); - if (len <= 0 || len > 32) { - logit("%s: bad challenge length %d", __func__, len); - goto failure; - } - memset(buf, 0, 32); - BN_bn2bin(challenge, buf + 32 - len); - if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || - ssh_digest_update(md, buf, 32) < 0 || - ssh_digest_update(md, session_id, 16) < 0 || - ssh_digest_final(md, mdbuf, sizeof(mdbuf)) < 0) - fatal("%s: md5 failed", __func__); - ssh_digest_free(md); - - /* Send the response. */ - if ((r = sshbuf_put_u8(msg, SSH_AGENT_RSA_RESPONSE)) != 0 || - (r = sshbuf_put(msg, mdbuf, sizeof(mdbuf))) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - goto send; } - - failure: - /* Unknown identity or protocol error. Send failure. */ - if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - send: if ((r = sshbuf_put_stringb(e->output, msg)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); - sshkey_free(key); - BN_clear_free(challenge); sshbuf_free(msg); } -#endif + static char * agent_decode_alg(struct sshkey *key, u_int flags) @@ -387,27 +274,24 @@ agent_decode_alg(struct sshkey *key, u_int flags) static void process_sign_request2(SocketEntry *e) { - u_char *blob, *data, *signature = NULL; - size_t blen, dlen, slen = 0; + const u_char *data; + u_char *signature = NULL; + size_t dlen, slen = 0; u_int compat = 0, flags; int r, ok = -1; struct sshbuf *msg; - struct sshkey *key; + struct sshkey *key = NULL; struct identity *id; if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); - if ((r = sshbuf_get_string(e->request, &blob, &blen)) != 0 || - (r = sshbuf_get_string(e->request, &data, &dlen)) != 0 || + if ((r = sshkey_froms(e->request, &key)) != 0 || + (r = sshbuf_get_string_direct(e->request, &data, &dlen)) != 0 || (r = sshbuf_get_u32(e->request, &flags)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (flags & SSH_AGENT_OLD_SIGNATURE) compat = SSH_BUG_SIGBLOB; - if ((r = sshkey_from_blob(blob, blen, &key)) != 0) { - error("%s: cannot parse key blob: %s", __func__, ssh_err(r)); - goto send; - } - if ((id = lookup_identity(key, 2)) == NULL) { + if ((id = lookup_identity(key)) == NULL) { verbose("%s: %s key not found", __func__, sshkey_type(key)); goto send; } @@ -435,90 +319,52 @@ process_sign_request2(SocketEntry *e) fatal("%s: buffer error: %s", __func__, ssh_err(r)); sshbuf_free(msg); - free(data); - free(blob); free(signature); } /* shared */ static void -process_remove_identity(SocketEntry *e, int version) +process_remove_identity(SocketEntry *e) { - size_t blen; int r, success = 0; struct sshkey *key = NULL; - u_char *blob; -#ifdef WITH_SSH1 - u_int bits; -#endif /* WITH_SSH1 */ + Identity *id; - switch (version) { -#ifdef WITH_SSH1 - case 1: - if ((key = sshkey_new(KEY_RSA1)) == NULL) { - error("%s: sshkey_new failed", __func__); - return; - } - if ((r = sshbuf_get_u32(e->request, &bits)) != 0 || - (r = sshbuf_get_bignum1(e->request, key->rsa->e)) != 0 || - (r = sshbuf_get_bignum1(e->request, key->rsa->n)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - - if (bits != sshkey_size(key)) - logit("Warning: identity keysize mismatch: " - "actual %u, announced %u", - sshkey_size(key), bits); - break; -#endif /* WITH_SSH1 */ - case 2: - if ((r = sshbuf_get_string(e->request, &blob, &blen)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - if ((r = sshkey_from_blob(blob, blen, &key)) != 0) - error("%s: sshkey_from_blob failed: %s", - __func__, ssh_err(r)); - free(blob); - break; + if ((r = sshkey_froms(e->request, &key)) != 0) { + error("%s: get key: %s", __func__, ssh_err(r)); + goto done; } - if (key != NULL) { - Identity *id = lookup_identity(key, version); - if (id != NULL) { - /* - * We have this key. Free the old key. Since we - * don't want to leave empty slots in the middle of - * the array, we actually free the key there and move - * all the entries between the empty slot and the end - * of the array. - */ - Idtab *tab = idtab_lookup(version); - if (tab->nentries < 1) - fatal("process_remove_identity: " - "internal error: tab->nentries %d", - tab->nentries); - TAILQ_REMOVE(&tab->idlist, id, next); - free_identity(id); - tab->nentries--; - success = 1; - } - sshkey_free(key); + if ((id = lookup_identity(key)) == NULL) { + debug("%s: key not found", __func__); + goto done; } + /* We have this key, free it. */ + if (idtab->nentries < 1) + fatal("%s: internal error: nentries %d", + __func__, idtab->nentries); + TAILQ_REMOVE(&idtab->idlist, id, next); + free_identity(id); + idtab->nentries--; + sshkey_free(key); + success = 1; + done: send_status(e, success); } static void -process_remove_all_identities(SocketEntry *e, int version) +process_remove_all_identities(SocketEntry *e) { - Idtab *tab = idtab_lookup(version); Identity *id; /* Loop over all identities and clear the keys. */ - for (id = TAILQ_FIRST(&tab->idlist); id; - id = TAILQ_FIRST(&tab->idlist)) { - TAILQ_REMOVE(&tab->idlist, id, next); + for (id = TAILQ_FIRST(&idtab->idlist); id; + id = TAILQ_FIRST(&idtab->idlist)) { + TAILQ_REMOVE(&idtab->idlist, id, next); free_identity(id); } /* Mark that there are no identities. */ - tab->nentries = 0; + idtab->nentries = 0; /* Send success. */ send_status(e, 1); @@ -530,24 +376,19 @@ reaper(void) { time_t deadline = 0, now = monotime(); Identity *id, *nxt; - int version; - Idtab *tab; - for (version = 1; version < 3; version++) { - tab = idtab_lookup(version); - for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { - nxt = TAILQ_NEXT(id, next); - if (id->death == 0) - continue; - if (now >= id->death) { - debug("expiring key '%s'", id->comment); - TAILQ_REMOVE(&tab->idlist, id, next); - free_identity(id); - tab->nentries--; - } else - deadline = (deadline == 0) ? id->death : - MINIMUM(deadline, id->death); - } + for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) { + nxt = TAILQ_NEXT(id, next); + if (id->death == 0) + continue; + if (now >= id->death) { + debug("expiring key '%s'", id->comment); + TAILQ_REMOVE(&idtab->idlist, id, next); + free_identity(id); + idtab->nentries--; + } else + deadline = (deadline == 0) ? id->death : + MINIMUM(deadline, id->death); } if (deadline == 0 || deadline <= now) return 0; @@ -555,54 +396,9 @@ reaper(void) return (deadline - now); } -/* - * XXX this and the corresponding serialisation function probably belongs - * in key.c - */ -#ifdef WITH_SSH1 -static int -agent_decode_rsa1(struct sshbuf *m, struct sshkey **kp) -{ - struct sshkey *k = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - - *kp = NULL; - if ((k = sshkey_new_private(KEY_RSA1)) == NULL) - return SSH_ERR_ALLOC_FAIL; - - if ((r = sshbuf_get_u32(m, NULL)) != 0 || /* ignored */ - (r = sshbuf_get_bignum1(m, k->rsa->n)) != 0 || - (r = sshbuf_get_bignum1(m, k->rsa->e)) != 0 || - (r = sshbuf_get_bignum1(m, k->rsa->d)) != 0 || - (r = sshbuf_get_bignum1(m, k->rsa->iqmp)) != 0 || - /* SSH1 and SSL have p and q swapped */ - (r = sshbuf_get_bignum1(m, k->rsa->q)) != 0 || /* p */ - (r = sshbuf_get_bignum1(m, k->rsa->p)) != 0) /* q */ - goto out; - - /* Generate additional parameters */ - if ((r = rsa_generate_additional_parameters(k->rsa)) != 0) - goto out; - /* enable blinding */ - if (RSA_blinding_on(k->rsa, NULL) != 1) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - - r = 0; /* success */ - out: - if (r == 0) - *kp = k; - else - sshkey_free(k); - return r; -} -#endif /* WITH_SSH1 */ - static void -process_add_identity(SocketEntry *e, int version) +process_add_identity(SocketEntry *e) { - Idtab *tab = idtab_lookup(version); Identity *id; int success = 0, confirm = 0; u_int seconds; @@ -612,17 +408,8 @@ process_add_identity(SocketEntry *e, int version) u_char ctype; int r = SSH_ERR_INTERNAL_ERROR; - switch (version) { -#ifdef WITH_SSH1 - case 1: - r = agent_decode_rsa1(e->request, &k); - break; -#endif /* WITH_SSH1 */ - case 2: - r = sshkey_private_deserialize(e->request, &k); - break; - } - if (r != 0 || k == NULL || + if ((r = sshkey_private_deserialize(e->request, &k)) != 0 || + k == NULL || (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) { error("%s: decode private key: %s", __func__, ssh_err(r)); goto err; @@ -658,12 +445,12 @@ process_add_identity(SocketEntry *e, int version) success = 1; if (lifetime && !death) death = monotime() + lifetime; - if ((id = lookup_identity(k, version)) == NULL) { + if ((id = lookup_identity(k)) == NULL) { id = xcalloc(1, sizeof(Identity)); id->key = k; - TAILQ_INSERT_TAIL(&tab->idlist, id, next); + TAILQ_INSERT_TAIL(&idtab->idlist, id, next); /* Increment the number of identities. */ - tab->nentries++; + idtab->nentries++; } else { sshkey_free(k); free(id->comment); @@ -724,17 +511,14 @@ process_lock_agent(SocketEntry *e, int lock) } static void -no_identities(SocketEntry *e, u_int type) +no_identities(SocketEntry *e) { struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); - if ((r = sshbuf_put_u8(msg, - (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ? - SSH_AGENT_RSA_IDENTITIES_ANSWER : - SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || + if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || (r = sshbuf_put_u32(msg, 0)) != 0 || (r = sshbuf_put_stringb(e->output, msg)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -746,13 +530,12 @@ static void process_add_smartcard_key(SocketEntry *e) { char *provider = NULL, *pin, canonical_provider[PATH_MAX]; - int r, i, version, count = 0, success = 0, confirm = 0; + int r, i, count = 0, success = 0, confirm = 0; u_int seconds; time_t death = 0; u_char type; struct sshkey **keys = NULL, *k; Identity *id; - Idtab *tab; if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) @@ -772,8 +555,7 @@ process_add_smartcard_key(SocketEntry *e) confirm = 1; break; default: - error("process_add_smartcard_key: " - "Unknown constraint type %d", type); + error("%s: Unknown constraint type %d", __func__, type); goto send; } } @@ -794,17 +576,15 @@ process_add_smartcard_key(SocketEntry *e) count = pkcs11_add_provider(canonical_provider, pin, &keys); for (i = 0; i < count; i++) { k = keys[i]; - version = k->type == KEY_RSA1 ? 1 : 2; - tab = idtab_lookup(version); - if (lookup_identity(k, version) == NULL) { + if (lookup_identity(k) == NULL) { id = xcalloc(1, sizeof(Identity)); id->key = k; id->provider = xstrdup(canonical_provider); id->comment = xstrdup(canonical_provider); /* XXX */ id->death = death; id->confirm = confirm; - TAILQ_INSERT_TAIL(&tab->idlist, id, next); - tab->nentries++; + TAILQ_INSERT_TAIL(&idtab->idlist, id, next); + idtab->nentries++; success = 1; } else { sshkey_free(k); @@ -822,9 +602,8 @@ static void process_remove_smartcard_key(SocketEntry *e) { char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX]; - int r, version, success = 0; + int r, success = 0; Identity *id, *nxt; - Idtab *tab; if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) @@ -838,25 +617,21 @@ process_remove_smartcard_key(SocketEntry *e) } debug("%s: remove %.100s", __func__, canonical_provider); - for (version = 1; version < 3; version++) { - tab = idtab_lookup(version); - for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { - nxt = TAILQ_NEXT(id, next); - /* Skip file--based keys */ - if (id->provider == NULL) - continue; - if (!strcmp(canonical_provider, id->provider)) { - TAILQ_REMOVE(&tab->idlist, id, next); - free_identity(id); - tab->nentries--; - } + for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) { + nxt = TAILQ_NEXT(id, next); + /* Skip file--based keys */ + if (id->provider == NULL) + continue; + if (!strcmp(canonical_provider, id->provider)) { + TAILQ_REMOVE(&idtab->idlist, id, next); + free_identity(id); + idtab->nentries--; } } if (pkcs11_del_provider(canonical_provider) == 0) success = 1; else - error("process_remove_smartcard_key:" - " pkcs11_del_provider failed"); + error("%s: pkcs11_del_provider failed", __func__); send: free(provider); send_status(e, success); @@ -865,88 +640,86 @@ process_remove_smartcard_key(SocketEntry *e) /* dispatch incoming messages */ -static void -process_message(SocketEntry *e) +static int +process_message(u_int socknum) { u_int msg_len; u_char type; const u_char *cp; int r; + SocketEntry *e; + + if (socknum >= sockets_alloc) { + fatal("%s: socket number %u >= allocated %u", + __func__, socknum, sockets_alloc); + } + e = &sockets[socknum]; if (sshbuf_len(e->input) < 5) - return; /* Incomplete message. */ + return 0; /* Incomplete message header. */ cp = sshbuf_ptr(e->input); msg_len = PEEK_U32(cp); - if (msg_len > 256 * 1024) { - close_socket(e); - return; + if (msg_len > AGENT_MAX_LEN) { + debug("%s: socket %u (fd=%d) message too long %u > %u", + __func__, socknum, e->fd, msg_len, AGENT_MAX_LEN); + return -1; } if (sshbuf_len(e->input) < msg_len + 4) - return; + return 0; /* Incomplete message body. */ /* move the current input to e->request */ sshbuf_reset(e->request); if ((r = sshbuf_get_stringb(e->input, e->request)) != 0 || - (r = sshbuf_get_u8(e->request, &type)) != 0) + (r = sshbuf_get_u8(e->request, &type)) != 0) { + if (r == SSH_ERR_MESSAGE_INCOMPLETE || + r == SSH_ERR_STRING_TOO_LARGE) { + debug("%s: buffer error: %s", __func__, ssh_err(r)); + return -1; + } fatal("%s: buffer error: %s", __func__, ssh_err(r)); + } + + debug("%s: socket %u (fd=%d) type %d", __func__, socknum, e->fd, type); /* check wheter agent is locked */ if (locked && type != SSH_AGENTC_UNLOCK) { sshbuf_reset(e->request); switch (type) { - case SSH_AGENTC_REQUEST_RSA_IDENTITIES: case SSH2_AGENTC_REQUEST_IDENTITIES: /* send empty lists */ - no_identities(e, type); + no_identities(e); break; default: /* send a fail message for all other request types */ send_status(e, 0); } - return; + return 0; } - debug("type %d", type); switch (type) { case SSH_AGENTC_LOCK: case SSH_AGENTC_UNLOCK: process_lock_agent(e, type == SSH_AGENTC_LOCK); break; -#ifdef WITH_SSH1 - /* ssh1 */ - case SSH_AGENTC_RSA_CHALLENGE: - process_authentication_challenge1(e); - break; - case SSH_AGENTC_REQUEST_RSA_IDENTITIES: - process_request_identities(e, 1); - break; - case SSH_AGENTC_ADD_RSA_IDENTITY: - case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED: - process_add_identity(e, 1); - break; - case SSH_AGENTC_REMOVE_RSA_IDENTITY: - process_remove_identity(e, 1); - break; -#endif case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: - process_remove_all_identities(e, 1); /* safe for !WITH_SSH1 */ + process_remove_all_identities(e); /* safe for !WITH_SSH1 */ break; /* ssh2 */ case SSH2_AGENTC_SIGN_REQUEST: process_sign_request2(e); break; case SSH2_AGENTC_REQUEST_IDENTITIES: - process_request_identities(e, 2); + process_request_identities(e); break; case SSH2_AGENTC_ADD_IDENTITY: case SSH2_AGENTC_ADD_ID_CONSTRAINED: - process_add_identity(e, 2); + process_add_identity(e); break; case SSH2_AGENTC_REMOVE_IDENTITY: - process_remove_identity(e, 2); + process_remove_identity(e); break; case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: - process_remove_all_identities(e, 2); + process_remove_all_identities(e); break; #ifdef ENABLE_PKCS11 case SSH_AGENTC_ADD_SMARTCARD_KEY: @@ -964,6 +737,7 @@ process_message(SocketEntry *e) send_status(e, 0); break; } + return 0; } static void @@ -1005,19 +779,141 @@ new_socket(sock_type type, int fd) } static int -prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, - struct timeval **tvpp) +handle_socket_read(u_int socknum) { - u_int i, sz; - int n = 0; - static struct timeval tv; + struct sockaddr_un sunaddr; + socklen_t slen; + uid_t euid; + gid_t egid; + int fd; + + slen = sizeof(sunaddr); + fd = accept(sockets[socknum].fd, (struct sockaddr *)&sunaddr, &slen); + if (fd < 0) { + error("accept from AUTH_SOCKET: %s", strerror(errno)); + return -1; + } + if (getpeereid(fd, &euid, &egid) < 0) { + error("getpeereid %d failed: %s", fd, strerror(errno)); + close(fd); + return -1; + } + if ((euid != 0) && (getuid() != euid)) { + error("uid mismatch: peer euid %u != uid %u", + (u_int) euid, (u_int) getuid()); + close(fd); + return -1; + } + new_socket(AUTH_CONNECTION, fd); + return 0; +} + +static int +handle_conn_read(u_int socknum) +{ + char buf[1024]; + ssize_t len; + int r; + + if ((len = read(sockets[socknum].fd, buf, sizeof(buf))) <= 0) { + if (len == -1) { + if (errno == EAGAIN || errno == EINTR) + return 0; + error("%s: read error on socket %u (fd %d): %s", + __func__, socknum, sockets[socknum].fd, + strerror(errno)); + } + return -1; + } + if ((r = sshbuf_put(sockets[socknum].input, buf, len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + explicit_bzero(buf, sizeof(buf)); + process_message(socknum); + return 0; +} + +static int +handle_conn_write(u_int socknum) +{ + ssize_t len; + int r; + + if (sshbuf_len(sockets[socknum].output) == 0) + return 0; /* shouldn't happen */ + if ((len = write(sockets[socknum].fd, + sshbuf_ptr(sockets[socknum].output), + sshbuf_len(sockets[socknum].output))) <= 0) { + if (len == -1) { + if (errno == EAGAIN || errno == EINTR) + return 0; + error("%s: read error on socket %u (fd %d): %s", + __func__, socknum, sockets[socknum].fd, + strerror(errno)); + } + return -1; + } + if ((r = sshbuf_consume(sockets[socknum].output, len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + return 0; +} + +static void +after_poll(struct pollfd *pfd, size_t npfd) +{ + size_t i; + u_int socknum; + + for (i = 0; i < npfd; i++) { + if (pfd[i].revents == 0) + continue; + /* Find sockets entry */ + for (socknum = 0; socknum < sockets_alloc; socknum++) { + if (sockets[socknum].type != AUTH_SOCKET && + sockets[socknum].type != AUTH_CONNECTION) + continue; + if (pfd[i].fd == sockets[socknum].fd) + break; + } + if (socknum >= sockets_alloc) { + error("%s: no socket for fd %d", __func__, pfd[i].fd); + continue; + } + /* Process events */ + switch (sockets[socknum].type) { + case AUTH_SOCKET: + if ((pfd[i].revents & (POLLIN|POLLERR)) != 0 && + handle_socket_read(socknum) != 0) + close_socket(&sockets[socknum]); + break; + case AUTH_CONNECTION: + if ((pfd[i].revents & (POLLIN|POLLERR)) != 0 && + handle_conn_read(socknum) != 0) { + close_socket(&sockets[socknum]); + break; + } + if ((pfd[i].revents & (POLLOUT|POLLHUP)) != 0 && + handle_conn_write(socknum) != 0) + close_socket(&sockets[socknum]); + break; + default: + break; + } + } +} + +static int +prepare_poll(struct pollfd **pfdp, size_t *npfdp, int *timeoutp) +{ + struct pollfd *pfd = *pfdp; + size_t i, j, npfd = 0; time_t deadline; + /* Count active sockets */ for (i = 0; i < sockets_alloc; i++) { switch (sockets[i].type) { case AUTH_SOCKET: case AUTH_CONNECTION: - n = MAXIMUM(n, sockets[i].fd); + npfd++; break; case AUTH_UNUSED: break; @@ -1026,28 +922,23 @@ prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, break; } } + if (npfd != *npfdp && + (pfd = recallocarray(pfd, *npfdp, npfd, sizeof(*pfd))) == NULL) + fatal("%s: recallocarray failed", __func__); + *pfdp = pfd; + *npfdp = npfd; - sz = howmany(n+1, NFDBITS) * sizeof(fd_mask); - if (*fdrp == NULL || sz > *nallocp) { - free(*fdrp); - free(*fdwp); - *fdrp = xmalloc(sz); - *fdwp = xmalloc(sz); - *nallocp = sz; - } - if (n < *fdl) - debug("XXX shrink: %d < %d", n, *fdl); - *fdl = n; - memset(*fdrp, 0, sz); - memset(*fdwp, 0, sz); - - for (i = 0; i < sockets_alloc; i++) { + for (i = j = 0; i < sockets_alloc; i++) { switch (sockets[i].type) { case AUTH_SOCKET: case AUTH_CONNECTION: - FD_SET(sockets[i].fd, *fdrp); + pfd[j].fd = sockets[i].fd; + pfd[j].revents = 0; + /* XXX backoff when input buffer full */ + pfd[j].events = POLLIN; if (sshbuf_len(sockets[i].output) > 0) - FD_SET(sockets[i].fd, *fdwp); + pfd[j].events |= POLLOUT; + j++; break; default: break; @@ -1058,98 +949,16 @@ prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, deadline = (deadline == 0) ? parent_alive_interval : MINIMUM(deadline, parent_alive_interval); if (deadline == 0) { - *tvpp = NULL; + *timeoutp = -1; /* INFTIM */ } else { - tv.tv_sec = deadline; - tv.tv_usec = 0; - *tvpp = &tv; + if (deadline > INT_MAX / 1000) + *timeoutp = INT_MAX / 1000; + else + *timeoutp = deadline * 1000; } return (1); } -static void -after_select(fd_set *readset, fd_set *writeset) -{ - struct sockaddr_un sunaddr; - socklen_t slen; - char buf[1024]; - int len, sock, r; - u_int i, orig_alloc; - uid_t euid; - gid_t egid; - - for (i = 0, orig_alloc = sockets_alloc; i < orig_alloc; i++) - switch (sockets[i].type) { - case AUTH_UNUSED: - break; - case AUTH_SOCKET: - if (FD_ISSET(sockets[i].fd, readset)) { - slen = sizeof(sunaddr); - sock = accept(sockets[i].fd, - (struct sockaddr *)&sunaddr, &slen); - if (sock < 0) { - error("accept from AUTH_SOCKET: %s", - strerror(errno)); - break; - } - if (getpeereid(sock, &euid, &egid) < 0) { - error("getpeereid %d failed: %s", - sock, strerror(errno)); - close(sock); - break; - } - if ((euid != 0) && (getuid() != euid)) { - error("uid mismatch: " - "peer euid %u != uid %u", - (u_int) euid, (u_int) getuid()); - close(sock); - break; - } - new_socket(AUTH_CONNECTION, sock); - } - break; - case AUTH_CONNECTION: - if (sshbuf_len(sockets[i].output) > 0 && - FD_ISSET(sockets[i].fd, writeset)) { - len = write(sockets[i].fd, - sshbuf_ptr(sockets[i].output), - sshbuf_len(sockets[i].output)); - if (len == -1 && (errno == EAGAIN || - errno == EWOULDBLOCK || - errno == EINTR)) - continue; - if (len <= 0) { - close_socket(&sockets[i]); - break; - } - if ((r = sshbuf_consume(sockets[i].output, - len)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); - } - if (FD_ISSET(sockets[i].fd, readset)) { - len = read(sockets[i].fd, buf, sizeof(buf)); - if (len == -1 && (errno == EAGAIN || - errno == EWOULDBLOCK || - errno == EINTR)) - continue; - if (len <= 0) { - close_socket(&sockets[i]); - break; - } - if ((r = sshbuf_put(sockets[i].input, - buf, len)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); - explicit_bzero(buf, sizeof(buf)); - process_message(&sockets[i]); - } - break; - default: - fatal("Unknown type %d", sockets[i].type); - } -} - static void cleanup_socket(void) { @@ -1209,9 +1018,7 @@ main(int ac, char **av) { int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0, s_flag = 0; int sock, fd, ch, result, saved_errno; - u_int nalloc; char *shell, *format, *pidstr, *agentsocket = NULL; - fd_set *readsetp = NULL, *writesetp = NULL; #ifdef HAVE_SETRLIMIT struct rlimit rlim; #endif @@ -1219,9 +1026,11 @@ main(int ac, char **av) extern char *optarg; pid_t pid; char pidstrbuf[1 + 3 * sizeof pid]; - struct timeval *tvp = NULL; size_t len; mode_t prev_mask; + int timeout = -1; /* INFTIM */ + struct pollfd *pfd = NULL; + size_t npfd = 0; ssh_malloc_init(); /* must be called before any mallocs */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ @@ -1442,15 +1251,14 @@ main(int ac, char **av) signal(SIGINT, (d_flag | D_flag) ? cleanup_handler : SIG_IGN); signal(SIGHUP, cleanup_handler); signal(SIGTERM, cleanup_handler); - nalloc = 0; if (pledge("stdio rpath cpath unix id proc exec", NULL) == -1) fatal("%s: pledge: %s", __progname, strerror(errno)); platform_pledge_agent(); while (1) { - prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp); - result = select(max_fd + 1, readsetp, writesetp, NULL, tvp); + prepare_poll(&pfd, &npfd, &timeout); + result = poll(pfd, npfd, timeout); saved_errno = errno; if (parent_alive_interval != 0) check_parent_exists(); @@ -1458,9 +1266,9 @@ main(int ac, char **av) if (result < 0) { if (saved_errno == EINTR) continue; - fatal("select: %s", strerror(saved_errno)); + fatal("poll: %s", strerror(saved_errno)); } else if (result > 0) - after_select(readsetp, writesetp); + after_poll(pfd, npfd); } /* NOTREACHED */ } diff --git a/ssh-gss.h b/ssh-gss.h index a99d7f08b30b..6593e422d929 100644 --- a/ssh-gss.h +++ b/ssh-gss.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-gss.h,v 1.11 2014/02/26 20:28:44 djm Exp $ */ +/* $OpenBSD: ssh-gss.h,v 1.12 2017/06/24 06:34:38 djm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. * @@ -128,6 +128,7 @@ OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); void ssh_gssapi_do_child(char ***, u_int *); void ssh_gssapi_cleanup_creds(void); void ssh_gssapi_storecreds(void); +const char *ssh_gssapi_displayname(void); #endif /* GSSAPI */ diff --git a/ssh-keygen.0 b/ssh-keygen.0 index 569297da42ed..fb2c02fe7f90 100644 --- a/ssh-keygen.0 +++ b/ssh-keygen.0 @@ -4,7 +4,7 @@ NAME ssh-keygen M-bM-^@M-^S authentication key generation, management and conversion SYNOPSIS - ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1] + ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa] [-N new_passphrase] [-C comment] [-f output_keyfile] ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile] ssh-keygen -i [-m key_format] [-f input_keyfile] @@ -21,24 +21,21 @@ SYNOPSIS ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point] ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines] [-j start_line] [-K checkpt] [-W generator] - ssh-keygen -s ca_key -I certificate_identity [-h] [-n principals] - [-O option] [-V validity_interval] [-z serial_number] file ... + ssh-keygen -s ca_key -I certificate_identity [-h] [-U] + [-D pkcs11_provider] [-n principals] [-O option] + [-V validity_interval] [-z serial_number] file ... ssh-keygen -L [-f input_keyfile] - ssh-keygen -A + ssh-keygen -A [-f prefix_path] ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number] file ... ssh-keygen -Q -f krl_file file ... DESCRIPTION ssh-keygen generates, manages and converts authentication keys for - ssh(1). ssh-keygen can create keys for use by SSH protocol versions 1 - and 2. Protocol 1 should not be used and is only offered to support - legacy devices. It suffers from a number of cryptographic weaknesses and - doesn't support many of the advanced features available for protocol 2. + ssh(1). ssh-keygen can create keys for use by SSH protocol version 2. The type of key to be generated is specified with the -t option. If - invoked without any arguments, ssh-keygen will generate an RSA key for - use in SSH protocol 2 connections. + invoked without any arguments, ssh-keygen will generate an RSA key. ssh-keygen is also used to generate groups for use in Diffie-Hellman group exchange (DH-GEX). See the MODULI GENERATION section for details. @@ -48,10 +45,10 @@ DESCRIPTION KEY REVOCATION LISTS section for details. Normally each user wishing to use SSH with public key authentication runs - this once to create the authentication key in ~/.ssh/identity, - ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 or ~/.ssh/id_rsa. - Additionally, the system administrator may use this to generate host - keys, as seen in /etc/rc. + this once to create the authentication key in ~/.ssh/id_dsa, + ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 or ~/.ssh/id_rsa. Additionally, the + system administrator may use this to generate host keys, as seen in + /etc/rc. Normally this program generates the key and asks for a file in which to store the private key. The public key is stored in a file with the same @@ -71,32 +68,33 @@ DESCRIPTION or forgotten, a new key must be generated and the corresponding public key copied to other machines. - For RSA1 keys and keys stored in the newer OpenSSH format, there is also - a comment field in the key file that is only for convenience to the user - to help identify the key. The comment can tell what the key is for, or - whatever is useful. The comment is initialized to M-bM-^@M-^\user@hostM-bM-^@M-^] when the - key is created, but can be changed using the -c option. + For keys stored in the newer OpenSSH format, there is also a comment + field in the key file that is only for convenience to the user to help + identify the key. The comment can tell what the key is for, or whatever + is useful. The comment is initialized to M-bM-^@M-^\user@hostM-bM-^@M-^] when the key is + created, but can be changed using the -c option. After a key is generated, instructions below detail where the keys should be placed to be activated. The options are as follows: - -A For each of the key types (rsa1, rsa, dsa, ecdsa and ed25519) for - which host keys do not exist, generate the host keys with the - default key file path, an empty passphrase, default bits for the - key type, and default comment. This is used by /etc/rc to - generate new host keys. + -A For each of the key types (rsa, dsa, ecdsa and ed25519) for which + host keys do not exist, generate the host keys with the default + key file path, an empty passphrase, default bits for the key + type, and default comment. If -f has also been specified, its + argument is used as a prefix to the default path for the + resulting host key files. This is used by /etc/rc to generate + new host keys. -a rounds - When saving a new-format private key (i.e. an ed25519 key or any - SSH protocol 2 key when the -o flag is set), this option - specifies the number of KDF (key derivation function) rounds - used. Higher numbers result in slower passphrase verification - and increased resistance to brute-force password cracking (should - the keys be stolen). + When saving a new-format private key (i.e. an ed25519 key or when + the -o flag is set), this option specifies the number of KDF (key + derivation function) rounds used. Higher numbers result in + slower passphrase verification and increased resistance to brute- + force password cracking (should the keys be stolen). - When screening DH-GEX candidates ( using the -T command). This + When screening DH-GEX candidates (using the -T command). This option specifies the number of primality tests to perform. -B Show the bubblebabble digest of specified private or public key @@ -117,10 +115,10 @@ DESCRIPTION Provides a new comment. -c Requests changing the comment in the private and public key - files. This operation is only supported for RSA1 keys and keys - stored in the newer OpenSSH format. The program will prompt for - the file containing the private keys, for the passphrase if the - key has one, and for the new comment. + files. This operation is only supported for keys stored in the + newer OpenSSH format. The program will prompt for the file + containing the private keys, for the passphrase if the key has + one, and for the new comment. -D pkcs11 Download the RSA public keys provided by the PKCS#11 shared @@ -200,11 +198,10 @@ DESCRIPTION -L Prints the contents of one or more certificates. - -l Show fingerprint of specified public key file. Private RSA1 keys - are also supported. For RSA and DSA keys ssh-keygen tries to - find the matching public key file and prints its fingerprint. If - combined with -v, a visual ASCII art representation of the key is - supplied with the fingerprint. + -l Show fingerprint of specified public key file. For RSA and DSA + keys ssh-keygen tries to find the matching public key file and + prints its fingerprint. If combined with -v, a visual ASCII art + representation of the key is supplied with the fingerprint. -M memory Specify the amount of memory to use (in megabytes) when @@ -228,14 +225,29 @@ DESCRIPTION -O option Specify a certificate option when signing a key. This option may - be specified multiple times. Please see the CERTIFICATES section - for details. The options that are valid for user certificates - are: + be specified multiple times. See also the CERTIFICATES section + for further details. The options that are valid for user + certificates are: clear Clear all enabled permissions. This is useful for clearing the default set of permissions so permissions may be added individually. + critical:name[=contents] + extension:name[=contents] + Includes an arbitrary certificate critical option or + extension. The specified name should include a domain + suffix, e.g. M-bM-^@M-^\name@example.comM-bM-^@M-^]. If contents is + specified then it is included as the contents of the + extension/option encoded as a string, otherwise the + extension/option is created with no contents (usually + indicating a flag). Extensions may be ignored by a + client or server that does not recognise them, whereas + unknown critical options will cause the certificate to be + refused. + + At present, no standard options are valid for host keys. + force-command=command Forces the execution of command instead of any shell or command specified by the user when the certificate is @@ -277,8 +289,6 @@ DESCRIPTION separated list of one or more address/netmask pairs in CIDR format. - At present, no options are valid for host keys. - -o Causes ssh-keygen to save private keys using the new OpenSSH format rather than the more compatible PEM format. The new format has increased resistance to brute-force password cracking @@ -322,10 +332,13 @@ DESCRIPTION Test DH group exchange candidate primes (generated using the -G option) for safety. - -t dsa | ecdsa | ed25519 | rsa | rsa1 + -t dsa | ecdsa | ed25519 | rsa Specifies the type of key to create. The possible values are - M-bM-^@M-^\rsa1M-bM-^@M-^] for protocol version 1 and M-bM-^@M-^\dsaM-bM-^@M-^], M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ed25519M-bM-^@M-^], or - M-bM-^@M-^\rsaM-bM-^@M-^] for protocol version 2. + M-bM-^@M-^\dsaM-bM-^@M-^], M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ed25519M-bM-^@M-^], or M-bM-^@M-^\rsaM-bM-^@M-^]. + + -U When used in combination with -s, this option indicates that a CA + key resides in a ssh-agent(1). See the CERTIFICATES section for + more information. -u Update a KRL. When specified with -k, keys listed via the command line are added to the existing KRL rather than a new KRL @@ -432,6 +445,12 @@ CERTIFICATES $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub + Similarly, it is possible for the CA key to be hosted in a ssh-agent(1). + This is indicated by the -U flag and, again, the CA key must be + identified by its public half. + + $ ssh-keygen -Us ca_key.pub -I key_id user_key.pub + In all cases, key_id is a "key identifier" that is logged by the server when the certificate is used for authentication. @@ -512,44 +531,28 @@ KEY REVOCATION LISTS was revoked. FILES - ~/.ssh/identity - Contains the protocol version 1 RSA authentication identity of - the user. This file should not be readable by anyone but the - user. It is possible to specify a passphrase when generating the - key; that passphrase will be used to encrypt the private part of - this file using 3DES. This file is not automatically accessed by - ssh-keygen but it is offered as the default file for the private - key. ssh(1) will read this file when a login attempt is made. - - ~/.ssh/identity.pub - Contains the protocol version 1 RSA public key for - authentication. The contents of this file should be added to - ~/.ssh/authorized_keys on all machines where the user wishes to - log in using RSA authentication. There is no need to keep the - contents of this file secret. - ~/.ssh/id_dsa ~/.ssh/id_ecdsa ~/.ssh/id_ed25519 ~/.ssh/id_rsa - Contains the protocol version 2 DSA, ECDSA, Ed25519 or RSA - authentication identity of the user. This file should not be - readable by anyone but the user. It is possible to specify a - passphrase when generating the key; that passphrase will be used - to encrypt the private part of this file using 128-bit AES. This - file is not automatically accessed by ssh-keygen but it is - offered as the default file for the private key. ssh(1) will - read this file when a login attempt is made. + Contains the DSA, ECDSA, Ed25519 or RSA authentication identity + of the user. This file should not be readable by anyone but the + user. It is possible to specify a passphrase when generating the + key; that passphrase will be used to encrypt the private part of + this file using 128-bit AES. This file is not automatically + accessed by ssh-keygen but it is offered as the default file for + the private key. ssh(1) will read this file when a login attempt + is made. ~/.ssh/id_dsa.pub ~/.ssh/id_ecdsa.pub ~/.ssh/id_ed25519.pub ~/.ssh/id_rsa.pub - Contains the protocol version 2 DSA, ECDSA, Ed25519 or RSA public - key for authentication. The contents of this file should be - added to ~/.ssh/authorized_keys on all machines where the user - wishes to log in using public key authentication. There is no - need to keep the contents of this file secret. + Contains the DSA, ECDSA, Ed25519 or RSA public key for + authentication. The contents of this file should be added to + ~/.ssh/authorized_keys on all machines where the user wishes to + log in using public key authentication. There is no need to keep + the contents of this file secret. /etc/moduli Contains Diffie-Hellman groups used for DH-GEX. The file format @@ -567,4 +570,4 @@ AUTHORS created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. -OpenBSD 6.0 June 16, 2016 OpenBSD 6.0 +OpenBSD 6.2 July 8, 2017 OpenBSD 6.2 diff --git a/ssh-keygen.1 b/ssh-keygen.1 index ce2213c7802b..5f1ec09b07a2 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.133 2016/06/16 06:10:45 jmc Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.144 2017/07/08 18:32:54 jmc Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: June 16 2016 $ +.Dd $Mdocdate: July 8 2017 $ .Dt SSH-KEYGEN 1 .Os .Sh NAME @@ -46,7 +46,7 @@ .Nm ssh-keygen .Op Fl q .Op Fl b Ar bits -.Op Fl t Cm dsa | ecdsa | ed25519 | rsa | rsa1 +.Op Fl t Cm dsa | ecdsa | ed25519 | rsa .Op Fl N Ar new_passphrase .Op Fl C Ar comment .Op Fl f Ar output_keyfile @@ -114,6 +114,8 @@ .Fl s Ar ca_key .Fl I Ar certificate_identity .Op Fl h +.Op Fl U +.Op Fl D Ar pkcs11_provider .Op Fl n Ar principals .Op Fl O Ar option .Op Fl V Ar validity_interval @@ -124,6 +126,7 @@ .Op Fl f Ar input_keyfile .Nm ssh-keygen .Fl A +.Op Fl f Ar prefix_path .Nm ssh-keygen .Fl k .Fl f Ar krl_file @@ -141,18 +144,14 @@ generates, manages and converts authentication keys for .Xr ssh 1 . .Nm -can create keys for use by SSH protocol versions 1 and 2. -Protocol 1 should not be used -and is only offered to support legacy devices. -It suffers from a number of cryptographic weaknesses -and doesn't support many of the advanced features available for protocol 2. +can create keys for use by SSH protocol version 2. .Pp The type of key to be generated is specified with the .Fl t option. If invoked without any arguments, .Nm -will generate an RSA key for use in SSH protocol 2 connections. +will generate an RSA key. .Pp .Nm is also used to generate groups for use in Diffie-Hellman group @@ -172,7 +171,6 @@ section for details. Normally each user wishing to use SSH with public key authentication runs this once to create the authentication key in -.Pa ~/.ssh/identity , .Pa ~/.ssh/id_dsa , .Pa ~/.ssh/id_ecdsa , .Pa ~/.ssh/id_ed25519 @@ -207,7 +205,7 @@ There is no way to recover a lost passphrase. If the passphrase is lost or forgotten, a new key must be generated and the corresponding public key copied to other machines. .Pp -For RSA1 keys and keys stored in the newer OpenSSH format, +For keys stored in the newer OpenSSH format, there is also a comment field in the key file that is only for convenience to the user to help identify the key. The comment can tell what the key is for, or whatever is useful. @@ -223,24 +221,26 @@ should be placed to be activated. The options are as follows: .Bl -tag -width Ds .It Fl A -For each of the key types (rsa1, rsa, dsa, ecdsa and ed25519) +For each of the key types (rsa, dsa, ecdsa and ed25519) for which host keys do not exist, generate the host keys with the default key file path, an empty passphrase, default bits for the key type, and default comment. +If +.Fl f +has also been specified, its argument is used as a prefix to the +default path for the resulting host key files. This is used by .Pa /etc/rc to generate new host keys. .It Fl a Ar rounds -When saving a new-format private key (i.e. an ed25519 key or any SSH protocol -2 key when the +When saving a new-format private key (i.e. an ed25519 key or when the .Fl o flag is set), this option specifies the number of KDF (key derivation function) rounds used. Higher numbers result in slower passphrase verification and increased resistance to brute-force password cracking (should the keys be stolen). .Pp -When screening DH-GEX candidates ( -using the +When screening DH-GEX candidates (using the .Fl T command). This option specifies the number of primality tests to perform. @@ -264,7 +264,7 @@ flag will be ignored. Provides a new comment. .It Fl c Requests changing the comment in the private and public key files. -This operation is only supported for RSA1 keys and keys stored in the +This operation is only supported for keys stored in the newer OpenSSH format. The program will prompt for the file containing the private keys, for the passphrase if the key has one, and for the new comment. @@ -384,7 +384,6 @@ section. Prints the contents of one or more certificates. .It Fl l Show fingerprint of specified public key file. -Private RSA1 keys are also supported. For RSA and DSA keys .Nm tries to find the matching public key file and prints its fingerprint. @@ -423,51 +422,81 @@ section for details. .It Fl O Ar option Specify a certificate option when signing a key. This option may be specified multiple times. -Please see the +See also the .Sx CERTIFICATES -section for details. +section for further details. The options that are valid for user certificates are: -.Bl -tag -width Ds +.Pp +.Bl -tag -width Ds -compact .It Ic clear Clear all enabled permissions. This is useful for clearing the default set of permissions so permissions may be added individually. +.Pp +.It Ic critical : Ns Ar name Ns Op Ns = Ns Ar contents +.It Ic extension : Ns Ar name Ns Op Ns = Ns Ar contents +Includes an arbitrary certificate critical option or extension. +The specified +.Ar name +should include a domain suffix, e.g.\& +.Dq name@example.com . +If +.Ar contents +is specified then it is included as the contents of the extension/option +encoded as a string, otherwise the extension/option is created with no +contents (usually indicating a flag). +Extensions may be ignored by a client or server that does not recognise them, +whereas unknown critical options will cause the certificate to be refused. +.Pp +At present, no standard options are valid for host keys. +.Pp .It Ic force-command Ns = Ns Ar command Forces the execution of .Ar command instead of any shell or command specified by the user when the certificate is used for authentication. +.Pp .It Ic no-agent-forwarding Disable .Xr ssh-agent 1 forwarding (permitted by default). +.Pp .It Ic no-port-forwarding Disable port forwarding (permitted by default). +.Pp .It Ic no-pty Disable PTY allocation (permitted by default). +.Pp .It Ic no-user-rc Disable execution of .Pa ~/.ssh/rc by .Xr sshd 8 (permitted by default). +.Pp .It Ic no-x11-forwarding Disable X11 forwarding (permitted by default). +.Pp .It Ic permit-agent-forwarding Allows .Xr ssh-agent 1 forwarding. +.Pp .It Ic permit-port-forwarding Allows port forwarding. +.Pp .It Ic permit-pty Allows PTY allocation. +.Pp .It Ic permit-user-rc Allows execution of .Pa ~/.ssh/rc by .Xr sshd 8 . +.Pp .It Ic permit-x11-forwarding Allows X11 forwarding. +.Pp .It Ic source-address Ns = Ns Ar address_list Restrict the source addresses from which the certificate is considered valid. The @@ -475,8 +504,6 @@ The is a comma-separated list of one or more address/netmask pairs in CIDR format. .El -.Pp -At present, no options are valid for host keys. .It Fl o Causes .Nm @@ -530,17 +557,22 @@ section for details. Test DH group exchange candidate primes (generated using the .Fl G option) for safety. -.It Fl t Cm dsa | ecdsa | ed25519 | rsa | rsa1 +.It Fl t Cm dsa | ecdsa | ed25519 | rsa Specifies the type of key to create. The possible values are -.Dq rsa1 -for protocol version 1 and .Dq dsa , .Dq ecdsa , .Dq ed25519 , or -.Dq rsa -for protocol version 2. +.Dq rsa . +.It Fl U +When used in combination with +.Fl s , +this option indicates that a CA key resides in a +.Xr ssh-agent 1 . +See the +.Sx CERTIFICATES +section for more information. .It Fl u Update a KRL. When specified with @@ -688,6 +720,14 @@ to .Pp .Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub .Pp +Similarly, it is possible for the CA key to be hosted in a +.Xr ssh-agent 1 . +This is indicated by the +.Fl U +flag and, again, the CA key must be identified by its public half. +.Pp +.Dl $ ssh-keygen -Us ca_key.pub -I key_id user_key.pub +.Pp In all cases, .Ar key_id is a "key identifier" that is logged by the server when the certificate @@ -795,31 +835,11 @@ will exit with a non-zero exit status. A zero exit status will only be returned if no key was revoked. .Sh FILES .Bl -tag -width Ds -compact -.It Pa ~/.ssh/identity -Contains the protocol version 1 RSA authentication identity of the user. -This file should not be readable by anyone but the user. -It is possible to -specify a passphrase when generating the key; that passphrase will be -used to encrypt the private part of this file using 3DES. -This file is not automatically accessed by -.Nm -but it is offered as the default file for the private key. -.Xr ssh 1 -will read this file when a login attempt is made. -.Pp -.It Pa ~/.ssh/identity.pub -Contains the protocol version 1 RSA public key for authentication. -The contents of this file should be added to -.Pa ~/.ssh/authorized_keys -on all machines -where the user wishes to log in using RSA authentication. -There is no need to keep the contents of this file secret. -.Pp .It Pa ~/.ssh/id_dsa .It Pa ~/.ssh/id_ecdsa .It Pa ~/.ssh/id_ed25519 .It Pa ~/.ssh/id_rsa -Contains the protocol version 2 DSA, ECDSA, Ed25519 or RSA +Contains the DSA, ECDSA, Ed25519 or RSA authentication identity of the user. This file should not be readable by anyone but the user. It is possible to @@ -835,7 +855,7 @@ will read this file when a login attempt is made. .It Pa ~/.ssh/id_ecdsa.pub .It Pa ~/.ssh/id_ed25519.pub .It Pa ~/.ssh/id_rsa.pub -Contains the protocol version 2 DSA, ECDSA, Ed25519 or RSA +Contains the DSA, ECDSA, Ed25519 or RSA public key for authentication. The contents of this file should be added to .Pa ~/.ssh/authorized_keys diff --git a/ssh-keygen.c b/ssh-keygen.c index f17af036bbfa..835f7d0169ba 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.299 2017/03/10 04:26:06 djm Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.307 2017/07/07 03:53:12 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -41,7 +41,6 @@ #include "xmalloc.h" #include "sshkey.h" -#include "rsa.h" #include "authfile.h" #include "uuencode.h" #include "sshbuf.h" @@ -59,6 +58,7 @@ #include "krl.h" #include "digest.h" #include "utf8.h" +#include "authfd.h" #ifdef WITH_OPENSSL # define DEFAULT_KEY_TYPE_NAME "rsa" @@ -121,6 +121,9 @@ char *identity_comment = NULL; /* Path to CA key when certifying keys. */ char *ca_key_path = NULL; +/* Prefer to use agent keys for CA signing */ +int prefer_agent = 0; + /* Certificate serial number */ unsigned long long cert_serial = 0; @@ -149,6 +152,15 @@ u_int32_t certflags_flags = CERTOPT_DEFAULT; char *certflags_command = NULL; char *certflags_src_addr = NULL; +/* Arbitrary extensions specified by user */ +struct cert_userext { + char *key; + char *val; + int crit; +}; +struct cert_userext *cert_userext; +size_t ncert_userext; + /* Conversion to/from various formats */ int convert_to = 0; int convert_from = 0; @@ -217,13 +229,21 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS; if (*bitsp > maxbits) fatal("key bits exceeds maximum %d", maxbits); - if (type == KEY_DSA && *bitsp != 1024) - fatal("DSA keys must be 1024 bits"); - else if (type != KEY_ECDSA && type != KEY_ED25519 && *bitsp < 1024) - fatal("Key must at least be 1024 bits"); - else if (type == KEY_ECDSA && sshkey_ecdsa_bits_to_nid(*bitsp) == -1) - fatal("Invalid ECDSA key length - valid lengths are " - "256, 384 or 521 bits"); + switch (type) { + case KEY_DSA: + if (*bitsp != 1024) + fatal("Invalid DSA key length: must be 1024 bits"); + break; + case KEY_RSA: + if (*bitsp < SSH_RSA_MINIMUM_MODULUS_SIZE) + fatal("Invalid RSA key length: minimum is %d bits", + SSH_RSA_MINIMUM_MODULUS_SIZE); + break; + case KEY_ECDSA: + if (sshkey_ecdsa_bits_to_nid(*bitsp) == -1) + fatal("Invalid ECDSA key length: valid lengths are " + "256, 384 or 521 bits"); + } #endif } @@ -237,9 +257,6 @@ ask_filename(struct passwd *pw, const char *prompt) name = _PATH_SSH_CLIENT_ID_RSA; else { switch (sshkey_type_from_name(key_type_name)) { - case KEY_RSA1: - name = _PATH_SSH_CLIENT_IDENTITY; - break; case KEY_DSA_CERT: case KEY_DSA: name = _PATH_SSH_CLIENT_ID_DSA; @@ -311,8 +328,6 @@ do_convert_to_ssh2(struct passwd *pw, struct sshkey *k) char comment[61]; int r; - if (k->type == KEY_RSA1) - fatal("version 1 keys are not supported"); if ((r = sshkey_to_blob(k, &blob, &len)) != 0) fatal("key_to_blob failed: %s", ssh_err(r)); /* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */ @@ -334,7 +349,6 @@ static void do_convert_to_pkcs8(struct sshkey *k) { switch (sshkey_type_plain(k->type)) { - case KEY_RSA1: case KEY_RSA: if (!PEM_write_RSA_PUBKEY(stdout, k->rsa)) fatal("PEM_write_RSA_PUBKEY failed"); @@ -359,7 +373,6 @@ static void do_convert_to_pem(struct sshkey *k) { switch (sshkey_type_plain(k->type)) { - case KEY_RSA1: case KEY_RSA: if (!PEM_write_RSAPublicKey(stdout, k->rsa)) fatal("PEM_write_RSAPublicKey failed"); @@ -478,7 +491,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) return NULL; } if ((key = sshkey_new_private(ktype)) == NULL) - fatal("key_new_private failed"); + fatal("sshkey_new_private failed"); free(type); switch (key->type) { @@ -514,7 +527,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) buffer_get_bignum_bits(b, key->rsa->iqmp); buffer_get_bignum_bits(b, key->rsa->q); buffer_get_bignum_bits(b, key->rsa->p); - if ((r = rsa_generate_additional_parameters(key->rsa)) != 0) + if ((r = ssh_rsa_generate_additional_parameters(key)) != 0) fatal("generate RSA parameters failed: %s", ssh_err(r)); break; } @@ -760,7 +773,7 @@ do_print_public(struct passwd *pw) fatal("%s: %s", identity_file, strerror(errno)); prv = load_identity(identity_file); if ((r = sshkey_write(prv, stdout)) != 0) - error("key_write failed: %s", ssh_err(r)); + error("sshkey_write failed: %s", ssh_err(r)); sshkey_free(prv); fprintf(stdout, "\n"); exit(0); @@ -816,13 +829,6 @@ try_read_key(char **cpp) struct sshkey *ret; int r; - if ((ret = sshkey_new(KEY_RSA1)) == NULL) - fatal("sshkey_new failed"); - /* Try RSA1 */ - if ((r = sshkey_read(ret, cpp)) == 0) - return ret; - /* Try modern */ - sshkey_free(ret); if ((ret = sshkey_new(KEY_UNSPEC)) == NULL) fatal("sshkey_new failed"); if ((r = sshkey_read(ret, cpp)) == 0) @@ -978,9 +984,6 @@ do_gen_all_hostkeys(struct passwd *pw) char *path; } key_types[] = { #ifdef WITH_OPENSSL -#ifdef WITH_SSH1 - { "rsa1", "RSA1", _PATH_HOST_KEY_FILE }, -#endif /* WITH_SSH1 */ { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE }, { "dsa", "DSA", _PATH_HOST_DSA_KEY_FILE }, #ifdef OPENSSL_HAS_ECC @@ -994,20 +997,38 @@ do_gen_all_hostkeys(struct passwd *pw) int first = 0; struct stat st; struct sshkey *private, *public; - char comment[1024]; + char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file; int i, type, fd, r; FILE *f; for (i = 0; key_types[i].key_type; i++) { - if (stat(key_types[i].path, &st) == 0) - continue; - if (errno != ENOENT) { + public = private = NULL; + prv_tmp = pub_tmp = prv_file = pub_file = NULL; + + xasprintf(&prv_file, "%s%s", + identity_file, key_types[i].path); + + /* Check whether private key exists and is not zero-length */ + if (stat(prv_file, &st) == 0) { + if (st.st_size != 0) + goto next; + } else if (errno != ENOENT) { error("Could not stat %s: %s", key_types[i].path, strerror(errno)); - first = 0; - continue; + goto failnext; } + /* + * Private key doesn't exist or is invalid; proceed with + * key generation. + */ + xasprintf(&prv_tmp, "%s%s.XXXXXXXXXX", + identity_file, key_types[i].path); + xasprintf(&pub_tmp, "%s%s.pub.XXXXXXXXXX", + identity_file, key_types[i].path); + xasprintf(&pub_file, "%s%s.pub", + identity_file, key_types[i].path); + if (first == 0) { first = 1; printf("%s: generating new host keys: ", __progname); @@ -1015,56 +1036,76 @@ do_gen_all_hostkeys(struct passwd *pw) printf("%s ", key_types[i].key_type_display); fflush(stdout); type = sshkey_type_from_name(key_types[i].key_type); - strlcpy(identity_file, key_types[i].path, sizeof(identity_file)); + if ((fd = mkstemp(prv_tmp)) == -1) { + error("Could not save your public key in %s: %s", + prv_tmp, strerror(errno)); + goto failnext; + } + close(fd); /* just using mkstemp() to generate/reserve a name */ bits = 0; type_bits_valid(type, NULL, &bits); if ((r = sshkey_generate(type, bits, &private)) != 0) { - error("key_generate failed: %s", ssh_err(r)); - first = 0; - continue; + error("sshkey_generate failed: %s", ssh_err(r)); + goto failnext; } if ((r = sshkey_from_private(private, &public)) != 0) fatal("sshkey_from_private failed: %s", ssh_err(r)); snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname); - if ((r = sshkey_save_private(private, identity_file, "", + if ((r = sshkey_save_private(private, prv_tmp, "", comment, use_new_format, new_format_cipher, rounds)) != 0) { error("Saving key \"%s\" failed: %s", - identity_file, ssh_err(r)); - sshkey_free(private); - sshkey_free(public); - first = 0; - continue; + prv_tmp, ssh_err(r)); + goto failnext; } - sshkey_free(private); - strlcat(identity_file, ".pub", sizeof(identity_file)); - fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) { - error("Could not save your public key in %s", - identity_file); - sshkey_free(public); - first = 0; - continue; + if ((fd = mkstemp(pub_tmp)) == -1) { + error("Could not save your public key in %s: %s", + pub_tmp, strerror(errno)); + goto failnext; } + (void)fchmod(fd, 0644); f = fdopen(fd, "w"); if (f == NULL) { - error("fdopen %s failed", identity_file); + error("fdopen %s failed: %s", pub_tmp, strerror(errno)); close(fd); - sshkey_free(public); - first = 0; - continue; + goto failnext; } if ((r = sshkey_write(public, f)) != 0) { error("write key failed: %s", ssh_err(r)); fclose(f); - sshkey_free(public); - first = 0; - continue; + goto failnext; } fprintf(f, " %s\n", comment); - fclose(f); - sshkey_free(public); + if (ferror(f) != 0) { + error("write key failed: %s", strerror(errno)); + fclose(f); + goto failnext; + } + if (fclose(f) != 0) { + error("key close failed: %s", strerror(errno)); + goto failnext; + } + /* Rename temporary files to their permanent locations. */ + if (rename(pub_tmp, pub_file) != 0) { + error("Unable to move %s into position: %s", + pub_file, strerror(errno)); + goto failnext; + } + if (rename(prv_tmp, prv_file) != 0) { + error("Unable to move %s into position: %s", + key_types[i].path, strerror(errno)); + failnext: + first = 0; + goto next; + } + next: + sshkey_free(private); + sshkey_free(public); + free(prv_tmp); + free(pub_tmp); + free(prv_file); + free(pub_file); } if (first != 0) printf("\n"); @@ -1436,9 +1477,8 @@ do_change_comment(struct passwd *pw) } } - if (private->type != KEY_RSA1 && private->type != KEY_ED25519 && - !use_new_format) { - error("Comments are only supported for RSA1 or keys stored in " + if (private->type != KEY_ED25519 && !use_new_format) { + error("Comments are only supported for keys stored in " "the new format (-o)."); explicit_bzero(passphrase, strlen(passphrase)); sshkey_free(private); @@ -1476,7 +1516,7 @@ do_change_comment(struct passwd *pw) explicit_bzero(passphrase, strlen(passphrase)); free(passphrase); if ((r = sshkey_from_private(private, &public)) != 0) - fatal("key_from_private failed: %s", ssh_err(r)); + fatal("sshkey_from_private failed: %s", ssh_err(r)); sshkey_free(private); strlcat(identity_file, ".pub", sizeof(identity_file)); @@ -1531,6 +1571,8 @@ add_string_option(struct sshbuf *c, const char *name, const char *value) static void prepare_options_buf(struct sshbuf *c, int which) { + size_t i; + sshbuf_reset(c); if ((which & OPTIONS_CRITICAL) != 0 && certflags_command != NULL) @@ -1553,6 +1595,17 @@ prepare_options_buf(struct sshbuf *c, int which) if ((which & OPTIONS_CRITICAL) != 0 && certflags_src_addr != NULL) add_string_option(c, "source-address", certflags_src_addr); + for (i = 0; i < ncert_userext; i++) { + if ((cert_userext[i].crit && (which & OPTIONS_EXTENSIONS)) || + (!cert_userext[i].crit && (which & OPTIONS_CRITICAL))) + continue; + if (cert_userext[i].val == NULL) + add_flag_option(c, cert_userext[i].key); + else { + add_string_option(c, cert_userext[i].key, + cert_userext[i].val); + } + } } static struct sshkey * @@ -1585,24 +1638,66 @@ load_pkcs11_key(char *path) #endif /* ENABLE_PKCS11 */ } +/* Signer for sshkey_certify_custom that uses the agent */ +static int +agent_signer(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, + const char *alg, u_int compat, void *ctx) +{ + int *agent_fdp = (int *)ctx; + + return ssh_agent_sign(*agent_fdp, key, sigp, lenp, + data, datalen, alg, compat); +} + static void do_ca_sign(struct passwd *pw, int argc, char **argv) { - int r, i, fd; + int r, i, fd, found, agent_fd = -1; u_int n; struct sshkey *ca, *public; char valid[64], *otmp, *tmp, *cp, *out, *comment, **plist = NULL; FILE *f; + struct ssh_identitylist *agent_ids; + size_t j; #ifdef ENABLE_PKCS11 pkcs11_init(1); #endif tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); if (pkcs11provider != NULL) { + /* If a PKCS#11 token was specified then try to use it */ if ((ca = load_pkcs11_key(tmp)) == NULL) fatal("No PKCS#11 key matching %s found", ca_key_path); - } else + } else if (prefer_agent) { + /* + * Agent signature requested. Try to use agent after making + * sure the public key specified is actually present in the + * agent. + */ + if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0) + fatal("Cannot load CA public key %s: %s", + tmp, ssh_err(r)); + if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) + fatal("Cannot use public key for CA signature: %s", + ssh_err(r)); + if ((r = ssh_fetch_identitylist(agent_fd, &agent_ids)) != 0) + fatal("Retrieve agent key list: %s", ssh_err(r)); + found = 0; + for (j = 0; j < agent_ids->nkeys; j++) { + if (sshkey_equal(ca, agent_ids->keys[j])) { + found = 1; + break; + } + } + if (!found) + fatal("CA key %s not found in agent", tmp); + ssh_free_identitylist(agent_ids); + ca->flags |= SSHKEY_FLAG_EXT; + } else { + /* CA key is assumed to be a private key on the filesystem */ ca = load_identity(tmp); + } free(tmp); if (key_type_name != NULL && @@ -1650,10 +1745,18 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) OPTIONS_EXTENSIONS); if ((r = sshkey_from_private(ca, &public->cert->signature_key)) != 0) - fatal("key_from_private (ca key): %s", ssh_err(r)); + fatal("sshkey_from_private (ca key): %s", ssh_err(r)); - if ((r = sshkey_certify(public, ca, key_type_name)) != 0) - fatal("Couldn't certify key %s: %s", tmp, ssh_err(r)); + if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) { + if ((r = sshkey_certify_custom(public, ca, + key_type_name, agent_signer, &agent_fd)) != 0) + fatal("Couldn't certify key %s via agent: %s", + tmp, ssh_err(r)); + } else { + if ((sshkey_certify(public, ca, key_type_name)) != 0) + fatal("Couldn't certify key %s: %s", + tmp, ssh_err(r)); + } if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0) *cp = '\0'; @@ -1789,7 +1892,8 @@ parse_cert_times(char *timespec) static void add_cert_option(char *opt) { - char *val; + char *val, *cp; + int iscrit = 0; if (strcasecmp(opt, "clear") == 0) certflags_flags = 0; @@ -1829,6 +1933,18 @@ add_cert_option(char *opt) if (addr_match_cidr_list(NULL, val) != 0) fatal("Invalid source-address list"); certflags_src_addr = xstrdup(val); + } else if (strncasecmp(opt, "extension:", 10) == 0 || + (iscrit = (strncasecmp(opt, "critical:", 9) == 0))) { + val = xstrdup(strchr(opt, ':') + 1); + if ((cp = strchr(val, '=')) != NULL) + *cp++ = '\0'; + cert_userext = xreallocarray(cert_userext, ncert_userext + 1, + sizeof(*cert_userext)); + cert_userext[ncert_userext].key = val; + cert_userext[ncert_userext].val = cp == NULL ? + NULL : xstrdup(cp); + cert_userext[ncert_userext].crit = iscrit; + ncert_userext++; } else fatal("Unsupported certificate option \"%s\"", opt); } @@ -1955,7 +2071,7 @@ do_show_cert(struct passwd *pw) if (*cp == '#' || *cp == '\0') continue; if ((key = sshkey_new(KEY_UNSPEC)) == NULL) - fatal("key_new"); + fatal("sshkey_new"); if ((r = sshkey_read(key, &cp)) != 0) { error("%s:%lu: invalid key: %s", path, lnum, ssh_err(r)); @@ -2101,7 +2217,7 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, */ } if ((key = sshkey_new(KEY_UNSPEC)) == NULL) - fatal("key_new"); + fatal("sshkey_new"); if ((r = sshkey_read(key, &cp)) != 0) fatal("%s:%lu: invalid key: %s", path, lnum, ssh_err(r)); @@ -2209,17 +2325,11 @@ do_check_krl(struct passwd *pw, int argc, char **argv) exit(ret); } -#ifdef WITH_SSH1 -# define RSA1_USAGE " | rsa1" -#else -# define RSA1_USAGE "" -#endif - static void usage(void) { fprintf(stderr, - "usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa%s]\n" + "usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa]\n" " [-N new_passphrase] [-C comment] [-f output_keyfile]\n" " ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]\n" " ssh-keygen -i [-m key_format] [-f input_keyfile]\n" @@ -2227,7 +2337,7 @@ usage(void) " ssh-keygen -y [-f input_keyfile]\n" " ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n" " ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]\n" - " ssh-keygen -B [-f input_keyfile]\n", RSA1_USAGE); + " ssh-keygen -B [-f input_keyfile]\n"); #ifdef ENABLE_PKCS11 fprintf(stderr, " ssh-keygen -D pkcs11\n"); @@ -2242,8 +2352,9 @@ usage(void) " ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines]\n" " [-j start_line] [-K checkpt] [-W generator]\n" #endif - " ssh-keygen -s ca_key -I certificate_identity [-h] [-n principals]\n" - " [-O option] [-V validity_interval] [-z serial_number] file ...\n" + " ssh-keygen -s ca_key -I certificate_identity [-h] [-U]\n" + " [-D pkcs11_provider] [-n principals] [-O option]\n" + " [-V validity_interval] [-z serial_number] file ...\n" " ssh-keygen -L [-f input_keyfile]\n" " ssh-keygen -A\n" " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n" @@ -2301,8 +2412,8 @@ main(int argc, char **argv) if (gethostname(hostname, sizeof(hostname)) < 0) fatal("gethostname: %s", strerror(errno)); - /* Remaining characters: UYdw */ - while ((opt = getopt(argc, argv, "ABHLQXceghiklopquvxy" + /* Remaining characters: Ydw */ + while ((opt = getopt(argc, argv, "ABHLQUXceghiklopquvxy" "C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:" "a:b:f:g:j:m:n:r:s:t:z:")) != -1) { switch (opt) { @@ -2429,6 +2540,9 @@ main(int argc, char **argv) case 'D': pkcs11provider = optarg; break; + case 'U': + prefer_agent = 1; + break; case 'u': update_krl = 1; break; @@ -2648,9 +2762,9 @@ main(int argc, char **argv) printf("Generating public/private %s key pair.\n", key_type_name); if ((r = sshkey_generate(type, bits, &private)) != 0) - fatal("key_generate failed"); + fatal("sshkey_generate failed"); if ((r = sshkey_from_private(private, &public)) != 0) - fatal("key_from_private failed: %s\n", ssh_err(r)); + fatal("sshkey_from_private failed: %s\n", ssh_err(r)); if (!have_identity) ask_filename(pw, "Enter file in which to save the key"); diff --git a/ssh-keyscan.0 b/ssh-keyscan.0 index e9d9f0d8b6e6..1a9751ef14a4 100644 --- a/ssh-keyscan.0 +++ b/ssh-keyscan.0 @@ -49,10 +49,9 @@ DESCRIPTION -t type Specifies the type of the key to fetch from the scanned hosts. - The possible values are M-bM-^@M-^\rsa1M-bM-^@M-^] for protocol version 1 and M-bM-^@M-^\dsaM-bM-^@M-^], - M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ed25519M-bM-^@M-^], or M-bM-^@M-^\rsaM-bM-^@M-^] for protocol version 2. Multiple - values may be specified by separating them with commas. The - default is to fetch M-bM-^@M-^\rsaM-bM-^@M-^], M-bM-^@M-^\ecdsaM-bM-^@M-^], and M-bM-^@M-^\ed25519M-bM-^@M-^] keys. + The possible values are M-bM-^@M-^\dsaM-bM-^@M-^], M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ed25519M-bM-^@M-^], or M-bM-^@M-^\rsaM-bM-^@M-^]. + Multiple values may be specified by separating them with commas. + The default is to fetch M-bM-^@M-^\rsaM-bM-^@M-^], M-bM-^@M-^\ecdsaM-bM-^@M-^], and M-bM-^@M-^\ed25519M-bM-^@M-^] keys. -v Verbose mode. Causes ssh-keyscan to print debugging messages about its progress. @@ -70,10 +69,6 @@ FILES 1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4 - Output format for RSA1 keys: - - host-or-namelist bits exponent modulus - Output format for RSA, DSA, ECDSA, and Ed25519 keys: host-or-namelist keytype base64-encoded-key @@ -108,4 +103,4 @@ BUGS This is because it opens a connection to the ssh port, reads the public key, and drops the connection as soon as it gets the key. -OpenBSD 6.0 November 8, 2015 OpenBSD 6.0 +OpenBSD 6.2 May 2, 2017 OpenBSD 6.2 diff --git a/ssh-keyscan.1 b/ssh-keyscan.1 index d29d9d906479..aa4a2ae838a0 100644 --- a/ssh-keyscan.1 +++ b/ssh-keyscan.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keyscan.1,v 1.38 2015/11/08 23:24:03 jmc Exp $ +.\" $OpenBSD: ssh-keyscan.1,v 1.40 2017/05/02 17:04:09 jmc Exp $ .\" .\" Copyright 1995, 1996 by David Mazieres . .\" @@ -6,7 +6,7 @@ .\" permitted provided that due credit is given to the author and the .\" OpenBSD project by leaving this copyright notice intact. .\" -.Dd $Mdocdate: November 8 2015 $ +.Dd $Mdocdate: May 2 2017 $ .Dt SSH-KEYSCAN 1 .Os .Sh NAME @@ -90,14 +90,11 @@ Default is 5 seconds. .It Fl t Ar type Specifies the type of the key to fetch from the scanned hosts. The possible values are -.Dq rsa1 -for protocol version 1 and .Dq dsa , .Dq ecdsa , .Dq ed25519 , or -.Dq rsa -for protocol version 2. +.Dq rsa . Multiple values may be specified by separating them with commas. The default is to fetch .Dq rsa , @@ -127,11 +124,6 @@ Input format: 1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4 .Ed .Pp -Output format for RSA1 keys: -.Bd -literal -host-or-namelist bits exponent modulus -.Ed -.Pp Output format for RSA, DSA, ECDSA, and Ed25519 keys: .Bd -literal host-or-namelist keytype base64-encoded-key diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 1f95239a37c6..258123ae80a8 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.109 2017/03/10 04:26:06 djm Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.115 2017/06/30 04:17:23 dtucker Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -32,7 +32,6 @@ #include "xmalloc.h" #include "ssh.h" -#include "ssh1.h" #include "sshbuf.h" #include "sshkey.h" #include "cipher.h" @@ -54,11 +53,13 @@ int IPv4or6 = AF_UNSPEC; int ssh_port = SSH_DEFAULT_PORT; -#define KT_RSA1 1 -#define KT_DSA 2 -#define KT_RSA 4 -#define KT_ECDSA 8 -#define KT_ED25519 16 +#define KT_DSA (1) +#define KT_RSA (1<<1) +#define KT_ECDSA (1<<2) +#define KT_ED25519 (1<<3) + +#define KT_MIN KT_DSA +#define KT_MAX KT_ED25519 int get_cert = 0; int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519; @@ -94,7 +95,7 @@ typedef struct Connection { int c_plen; /* Packet length field for ssh packet */ int c_len; /* Total bytes which must be read. */ int c_off; /* Length of data read so far. */ - int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */ + int c_keytype; /* Only one of KT_* */ sig_atomic_t c_done; /* SSH2 done */ char *c_namebase; /* Address to free for c_name and c_namelist */ char *c_name; /* Hostname of connection for errors */ @@ -187,52 +188,6 @@ strnnsep(char **stringp, char *delim) return (tok); } -#ifdef WITH_SSH1 -static struct sshkey * -keygrab_ssh1(con *c) -{ - static struct sshkey *rsa; - static struct sshbuf *msg; - int r; - u_char type; - - if (rsa == NULL) { - if ((rsa = sshkey_new(KEY_RSA1)) == NULL) { - error("%s: sshkey_new failed", __func__); - return NULL; - } - if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); - } - if ((r = sshbuf_put(msg, c->c_data, c->c_plen)) != 0 || - (r = sshbuf_consume(msg, 8 - (c->c_plen & 7))) != 0 || /* padding */ - (r = sshbuf_get_u8(msg, &type)) != 0) - goto buf_err; - if (type != (int) SSH_SMSG_PUBLIC_KEY) { - error("%s: invalid packet type", c->c_name); - sshbuf_reset(msg); - return NULL; - } - if ((r = sshbuf_consume(msg, 8)) != 0 || /* cookie */ - /* server key */ - (r = sshbuf_get_u32(msg, NULL)) != 0 || - (r = sshbuf_get_bignum1(msg, NULL)) != 0 || - (r = sshbuf_get_bignum1(msg, NULL)) != 0 || - /* host key */ - (r = sshbuf_get_u32(msg, NULL)) != 0 || - (r = sshbuf_get_bignum1(msg, rsa->rsa->e)) != 0 || - (r = sshbuf_get_bignum1(msg, rsa->rsa->n)) != 0) { - buf_err: - error("%s: buffer error: %s", __func__, ssh_err(r)); - sshbuf_reset(msg); - return NULL; - } - - sshbuf_reset(msg); - - return (rsa); -} -#endif static int key_print_wrapper(struct sshkey *hostkey, struct ssh *ssh) @@ -267,7 +222,6 @@ keygrab_ssh2(con *c) char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; int r; - enable_compat20(); switch (c->c_keytype) { case KT_DSA: myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? @@ -317,7 +271,7 @@ keygrab_ssh2(con *c) * do the key-exchange until an error occurs or until * the key_print_wrapper() callback sets c_done. */ - ssh_dispatch_run(c->c_ssh, DISPATCH_BLOCK, &c->c_done, c->c_ssh); + ssh_dispatch_run(c->c_ssh, DISPATCH_BLOCK, &c->c_done); } static void @@ -436,7 +390,6 @@ confree(int s) { if (s >= maxfd || fdcon[s].c_status == CS_UNUSED) fatal("confree: attempt to free bad fdno %d", s); - close(s); free(fdcon[s].c_namebase); free(fdcon[s].c_output_name); if (fdcon[s].c_status == CS_KEYS) @@ -447,7 +400,8 @@ confree(int s) ssh_packet_close(fdcon[s].c_ssh); free(fdcon[s].c_ssh); fdcon[s].c_ssh = NULL; - } + } else + close(s); TAILQ_REMOVE(&tq, &fdcon[s], c_link); FD_CLR(s, read_wait); ncon--; @@ -482,6 +436,20 @@ congreet(int s) size_t bufsiz; con *c = &fdcon[s]; + /* send client banner */ + n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", + PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2); + if (n < 0 || (size_t)n >= sizeof(buf)) { + error("snprintf: buffer too small"); + confree(s); + return; + } + if (atomicio(vwrite, s, buf, n) != (size_t)n) { + error("write (%s): %s", c->c_name, strerror(errno)); + confree(s); + return; + } + for (;;) { memset(buf, '\0', sizeof(buf)); bufsiz = sizeof(buf); @@ -524,38 +492,14 @@ congreet(int s) c->c_ssh->compat = compat_datafellows(remote_version); else c->c_ssh->compat = 0; - if (c->c_keytype != KT_RSA1) { - if (!ssh2_capable(remote_major, remote_minor)) { - debug("%s doesn't support ssh2", c->c_name); - confree(s); - return; - } - } else if (remote_major != 1) { - debug("%s doesn't support ssh1", c->c_name); + if (!ssh2_capable(remote_major, remote_minor)) { + debug("%s doesn't support ssh2", c->c_name); confree(s); return; } fprintf(stderr, "# %s:%d %s\n", c->c_name, ssh_port, chop(buf)); - n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", - c->c_keytype == KT_RSA1? PROTOCOL_MAJOR_1 : PROTOCOL_MAJOR_2, - c->c_keytype == KT_RSA1? PROTOCOL_MINOR_1 : PROTOCOL_MINOR_2); - if (n < 0 || (size_t)n >= sizeof(buf)) { - error("snprintf: buffer too small"); - confree(s); - return; - } - if (atomicio(vwrite, s, buf, n) != (size_t)n) { - error("write (%s): %s", c->c_name, strerror(errno)); - confree(s); - return; - } - if (c->c_keytype != KT_RSA1) { - keygrab_ssh2(c); - confree(s); - return; - } - c->c_status = CS_SIZE; - contouch(s); + keygrab_ssh2(c); + confree(s); } static void @@ -585,12 +529,6 @@ conread(int s) c->c_data = xmalloc(c->c_len); c->c_status = CS_KEYS; break; -#ifdef WITH_SSH1 - case CS_KEYS: - keyprint(c, keygrab_ssh1(c)); - confree(s); - return; -#endif default: fatal("conread: invalid status %d", c->c_status); break; @@ -659,7 +597,7 @@ do_host(char *host) if (name == NULL) return; - for (j = KT_RSA1; j <= KT_ED25519; j *= 2) { + for (j = KT_MIN; j <= KT_MAX; j *= 2) { if (get_keytypes & j) { while (ncon >= MAXCON) conloop(); @@ -756,11 +694,6 @@ main(int argc, char **argv) int type = sshkey_type_from_name(tname); switch (type) { -#ifdef WITH_SSH1 - case KEY_RSA1: - get_keytypes |= KT_RSA1; - break; -#endif case KEY_DSA: get_keytypes |= KT_DSA; break; diff --git a/ssh-keysign.0 b/ssh-keysign.0 index 34a451d62b59..d855ad07a8e7 100644 --- a/ssh-keysign.0 +++ b/ssh-keysign.0 @@ -49,4 +49,4 @@ HISTORY AUTHORS Markus Friedl -OpenBSD 6.0 February 17, 2016 OpenBSD 6.0 +OpenBSD 6.2 February 17, 2016 OpenBSD 6.2 diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c index fac0167e6f14..a79c872101fb 100644 --- a/ssh-pkcs11-client.c +++ b/ssh-pkcs11-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11-client.c,v 1.6 2015/12/11 00:20:04 mmcc Exp $ */ +/* $OpenBSD: ssh-pkcs11-client.c,v 1.7 2017/05/30 08:52:19 markus Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -106,7 +106,7 @@ static int pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding) { - Key key; + struct sshkey key; /* XXX */ u_char *blob, *signature = NULL; u_int blen, slen = 0; int ret = -1; @@ -186,7 +186,7 @@ pkcs11_start_helper(void) int pkcs11_add_provider(char *name, char *pin, Key ***keysp) { - Key *k; + struct sshkey *k; int i, nkeys; u_char *blob; u_int blen; diff --git a/ssh-pkcs11-helper.0 b/ssh-pkcs11-helper.0 index 1b58361a6b75..93e5565b7ae0 100644 --- a/ssh-pkcs11-helper.0 +++ b/ssh-pkcs11-helper.0 @@ -22,4 +22,4 @@ HISTORY AUTHORS Markus Friedl -OpenBSD 6.0 July 16, 2013 OpenBSD 6.0 +OpenBSD 6.2 July 16, 2013 OpenBSD 6.2 diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c index 53f41c555f40..fd3039c14272 100644 --- a/ssh-pkcs11-helper.c +++ b/ssh-pkcs11-helper.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11-helper.c,v 1.12 2016/02/15 09:47:49 dtucker Exp $ */ +/* $OpenBSD: ssh-pkcs11-helper.c,v 1.13 2017/05/30 08:52:19 markus Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -42,7 +42,7 @@ /* borrows code from sftp-server and ssh-agent */ struct pkcs11_keyinfo { - Key *key; + struct sshkey *key; char *providername; TAILQ_ENTRY(pkcs11_keyinfo) next; }; @@ -60,7 +60,7 @@ Buffer iqueue; Buffer oqueue; static void -add_key(Key *k, char *name) +add_key(struct sshkey *k, char *name) { struct pkcs11_keyinfo *ki; @@ -87,8 +87,8 @@ del_keys_by_name(char *name) } /* lookup matching 'private' key */ -static Key * -lookup_key(Key *k) +static struct sshkey * +lookup_key(struct sshkey *k) { struct pkcs11_keyinfo *ki; @@ -114,7 +114,7 @@ static void process_add(void) { char *name, *pin; - Key **keys; + struct sshkey **keys; int i, nkeys; u_char *blob; u_int blen; @@ -170,7 +170,7 @@ process_sign(void) u_char *blob, *data, *signature = NULL; u_int blen, dlen, slen = 0; int ok = -1; - Key *key, *found; + struct sshkey *key, *found; Buffer msg; blob = get_string(&blen); diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index aaf712d9a5ba..b37491c5d68d 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11.c,v 1.23 2016/10/28 03:33:52 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11.c,v 1.25 2017/05/31 09:15:42 deraadt Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -537,7 +537,8 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, } if (rsa && rsa->n && rsa->e && pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { - key = sshkey_new(KEY_UNSPEC); + if ((key = sshkey_new(KEY_UNSPEC)) == NULL) + fatal("sshkey_new failed"); key->rsa = rsa; key->type = KEY_RSA; key->flags |= SSHKEY_FLAG_EXT; @@ -545,8 +546,8 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, sshkey_free(key); } else { /* expand key array and add key */ - *keysp = xreallocarray(*keysp, *nkeys + 1, - sizeof(struct sshkey *)); + *keysp = xrecallocarray(*keysp, *nkeys, + *nkeys + 1, sizeof(struct sshkey *)); (*keysp)[*nkeys] = key; *nkeys = *nkeys + 1; debug("have %d keys", *nkeys); diff --git a/ssh-rsa.c b/ssh-rsa.c index cde05df10143..f570ae6d40aa 100644 --- a/ssh-rsa.c +++ b/ssh-rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-rsa.c,v 1.60 2016/09/12 23:39:34 djm Exp $ */ +/* $OpenBSD: ssh-rsa.c,v 1.62 2017/07/01 13:50:45 djm Exp $ */ /* * Copyright (c) 2000, 2003 Markus Friedl * @@ -78,6 +78,41 @@ rsa_hash_alg_nid(int type) } } +/* calculate p-1 and q-1 */ +int +ssh_rsa_generate_additional_parameters(struct sshkey *key) +{ + RSA *rsa; + BIGNUM *aux = NULL; + BN_CTX *ctx = NULL; + int r; + + if (key == NULL || key->rsa == NULL || + sshkey_type_plain(key->type) != KEY_RSA) + return SSH_ERR_INVALID_ARGUMENT; + + if ((ctx = BN_CTX_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((aux = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + rsa = key->rsa; + + if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) || + (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) || + (BN_sub(aux, rsa->p, BN_value_one()) == 0) || + (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + r = 0; + out: + BN_clear_free(aux); + BN_CTX_free(ctx); + return r; +} + /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ int ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, @@ -99,9 +134,10 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, else hash_alg = rsa_hash_alg_from_ident(alg_ident); if (key == NULL || key->rsa == NULL || hash_alg == -1 || - sshkey_type_plain(key->type) != KEY_RSA || - BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) + sshkey_type_plain(key->type) != KEY_RSA) return SSH_ERR_INVALID_ARGUMENT; + if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) + return SSH_ERR_KEY_LENGTH; slen = RSA_size(key->rsa); if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) return SSH_ERR_INVALID_ARGUMENT; @@ -172,9 +208,10 @@ ssh_rsa_verify(const struct sshkey *key, if (key == NULL || key->rsa == NULL || sshkey_type_plain(key->type) != KEY_RSA || - BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE || sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; + if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) + return SSH_ERR_KEY_LENGTH; if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; diff --git a/ssh.0 b/ssh.0 index 67ce809bb28e..f920dd97e010 100644 --- a/ssh.0 +++ b/ssh.0 @@ -4,7 +4,7 @@ NAME ssh M-bM-^@M-^S OpenSSH SSH client (remote login program) SYNOPSIS - ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec] + ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port] [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file] [-J [user@]host[:port]] [-L address] [-l login_name] [-m mac_spec] @@ -28,10 +28,6 @@ DESCRIPTION The options are as follows: - -1 Forces ssh to try protocol version 1 only. - - -2 Forces ssh to try protocol version 2 only. - -4 Forces ssh to use IPv4 addresses only. -6 Forces ssh to use IPv6 addresses only. @@ -58,21 +54,16 @@ DESCRIPTION -C Requests compression of all data (including stdin, stdout, stderr, and data for forwarded X11, TCP and UNIX-domain connections). The compression algorithm is the same used by - gzip(1), and the M-bM-^@M-^\levelM-bM-^@M-^] can be controlled by the - CompressionLevel option for protocol version 1. Compression is - desirable on modem lines and other slow connections, but will - only slow down things on fast networks. The default value can be - set on a host-by-host basis in the configuration files; see the - Compression option. + gzip(1). Compression is desirable on modem lines and other slow + connections, but will only slow down things on fast networks. + The default value can be set on a host-by-host basis in the + configuration files; see the Compression option. -c cipher_spec Selects the cipher specification for encrypting the session. - - Protocol version 1 allows specification of a single cipher. The - supported values are M-bM-^@M-^\3desM-bM-^@M-^], M-bM-^@M-^\blowfishM-bM-^@M-^], and M-bM-^@M-^\desM-bM-^@M-^]. For protocol - version 2, cipher_spec is a comma-separated list of ciphers - listed in order of preference. See the Ciphers keyword in - ssh_config(5) for more information. + cipher_spec is a comma-separated list of ciphers listed in order + of preference. See the Ciphers keyword in ssh_config(5) for more + information. -D [bind_address:]port Specifies a local M-bM-^@M-^\dynamicM-bM-^@M-^] application-level port forwarding. @@ -137,10 +128,9 @@ DESCRIPTION -i identity_file Selects a file from which the identity (private key) for public - key authentication is read. The default is ~/.ssh/identity for - protocol version 1, and ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, - ~/.ssh/id_ed25519 and ~/.ssh/id_rsa for protocol version 2. - Identity files may also be specified on a per-host basis in the + key authentication is read. The default is ~/.ssh/id_dsa, + ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and ~/.ssh/id_rsa. Identity + files may also be specified on a per-host basis in the configuration file. It is possible to have multiple -i options (and multiple identities specified in configuration files). If no certificates have been explicitly specified by the @@ -243,11 +233,9 @@ DESCRIPTION CertificateFile ChallengeResponseAuthentication CheckHostIP - Cipher Ciphers ClearAllForwardings Compression - CompressionLevel ConnectionAttempts ConnectTimeout ControlMaster @@ -292,17 +280,15 @@ DESCRIPTION PKCS11Provider Port PreferredAuthentications - Protocol ProxyCommand ProxyJump ProxyUseFdpass PubkeyAcceptedKeyTypes PubkeyAuthentication RekeyLimit + RemoteCommand RemoteForward RequestTTY - RhostsRSAAuthentication - RSAAuthentication SendEnv ServerAliveInterval ServerAliveCountMax @@ -340,14 +326,20 @@ DESCRIPTION -R [bind_address:]port:local_socket -R remote_socket:host:hostport -R remote_socket:local_socket + -R [bind_address:]port Specifies that connections to the given TCP port or Unix socket - on the remote (server) host are to be forwarded to the given host - and port, or Unix socket, on the local side. This works by - allocating a socket to listen to either a TCP port or to a Unix - socket on the remote side. Whenever a connection is made to this - port or Unix socket, the connection is forwarded over the secure - channel, and a connection is made to either host port hostport, - or local_socket, from the local machine. + on the remote (server) host are to be forwarded to the local + side. + + This works by allocating a socket to listen to either a TCP port + or to a Unix socket on the remote side. Whenever a connection is + made to this port or Unix socket, the connection is forwarded + over the secure channel, and a connection is made from the local + machine to either an explicit destination specified by host port + hostport, or local_socket, or, if no explicit destination was + specified, ssh will act as a SOCKS 4/5 proxy and forward + connections to the destinations requested by the remote SOCKS + client. Port forwardings can also be specified in the configuration file. Privileged ports can be forwarded only when logging in as root on @@ -438,12 +430,7 @@ DESCRIPTION and configuration options are described in ssh_config(5). AUTHENTICATION - The OpenSSH SSH client supports SSH protocols 1 and 2. The default is to - use protocol 2 only, though this can be changed via the Protocol option - in ssh_config(5) or the -1 and -2 options (see above). Protocol 1 should - not be used and is only offered to support legacy devices. It suffers - from a number of cryptographic weaknesses and doesn't support many of the - advanced features available for protocol 2. + The OpenSSH SSH client supports SSH protocol 2. The methods available for authentication are: GSSAPI-based authentication, host-based authentication, public key authentication, @@ -481,11 +468,15 @@ AUTHENTICATION proves that it has access to the private key and the server checks that the corresponding public key is authorized to accept the account. + The server may inform the client of errors that prevented public key + authentication from succeeding after authentication completes using a + different method. These may be viewed by increasing the LogLevel to + DEBUG or higher (e.g. by using the -v flag). + The user creates his/her key pair by running ssh-keygen(1). This stores - the private key in ~/.ssh/identity (protocol 1), ~/.ssh/id_dsa (DSA), - ~/.ssh/id_ecdsa (ECDSA), ~/.ssh/id_ed25519 (Ed25519), or ~/.ssh/id_rsa - (RSA) and stores the public key in ~/.ssh/identity.pub (protocol 1), - ~/.ssh/id_dsa.pub (DSA), ~/.ssh/id_ecdsa.pub (ECDSA), + the private key in ~/.ssh/id_dsa (DSA), ~/.ssh/id_ecdsa (ECDSA), + ~/.ssh/id_ed25519 (Ed25519), or ~/.ssh/id_rsa (RSA) and stores the public + key in ~/.ssh/id_dsa.pub (DSA), ~/.ssh/id_ecdsa.pub (ECDSA), ~/.ssh/id_ed25519.pub (Ed25519), or ~/.ssh/id_rsa.pub (RSA) in the user's home directory. The user should then copy the public key to ~/.ssh/authorized_keys in his/her home directory on the remote machine. @@ -845,7 +836,6 @@ FILES Contains additional definitions for environment variables; see ENVIRONMENT, above. - ~/.ssh/identity ~/.ssh/id_dsa ~/.ssh/id_ecdsa ~/.ssh/id_ed25519 @@ -858,7 +848,6 @@ FILES will be used to encrypt the sensitive part of this file using 3DES. - ~/.ssh/identity.pub ~/.ssh/id_dsa.pub ~/.ssh/id_ecdsa.pub ~/.ssh/id_ed25519.pub @@ -968,4 +957,4 @@ AUTHORS created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. -OpenBSD 6.0 July 16, 2016 OpenBSD 6.0 +OpenBSD 6.2 September 21, 2017 OpenBSD 6.2 diff --git a/ssh.1 b/ssh.1 index 4011c65aa662..2ab1697f95de 100644 --- a/ssh.1 +++ b/ssh.1 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh.1,v 1.376 2016/07/16 06:57:55 jmc Exp $ -.Dd $Mdocdate: July 16 2016 $ +.\" $OpenBSD: ssh.1,v 1.384 2017/09/21 19:16:53 markus Exp $ +.Dd $Mdocdate: September 21 2017 $ .Dt SSH 1 .Os .Sh NAME @@ -43,7 +43,7 @@ .Sh SYNOPSIS .Nm ssh .Bk -words -.Op Fl 1246AaCfGgKkMNnqsTtVvXxYy +.Op Fl 46AaCfGgKkMNnqsTtVvXxYy .Op Fl b Ar bind_address .Op Fl c Ar cipher_spec .Op Fl D Oo Ar bind_address : Oc Ns Ar port @@ -95,16 +95,6 @@ it is executed on the remote host instead of a login shell. The options are as follows: .Pp .Bl -tag -width Ds -compact -.It Fl 1 -Forces -.Nm -to try protocol version 1 only. -.Pp -.It Fl 2 -Forces -.Nm -to try protocol version 2 only. -.Pp .It Fl 4 Forces .Nm @@ -144,12 +134,7 @@ data for forwarded X11, TCP and .Ux Ns -domain connections). The compression algorithm is the same used by -.Xr gzip 1 , -and the -.Dq level -can be controlled by the -.Cm CompressionLevel -option for protocol version 1. +.Xr gzip 1 . Compression is desirable on modem lines and other slow connections, but will only slow down things on fast networks. The default value can be set on a host-by-host basis in the @@ -159,14 +144,6 @@ option. .Pp .It Fl c Ar cipher_spec Selects the cipher specification for encrypting the session. -.Pp -Protocol version 1 allows specification of a single cipher. -The supported values are -.Dq 3des , -.Dq blowfish , -and -.Dq des . -For protocol version 2, .Ar cipher_spec is a comma-separated list of ciphers listed in order of preference. @@ -290,14 +267,11 @@ private RSA key. Selects a file from which the identity (private key) for public key authentication is read. The default is -.Pa ~/.ssh/identity -for protocol version 1, and .Pa ~/.ssh/id_dsa , .Pa ~/.ssh/id_ecdsa , .Pa ~/.ssh/id_ed25519 and -.Pa ~/.ssh/id_rsa -for protocol version 2. +.Pa ~/.ssh/id_rsa . Identity files may also be specified on a per-host basis in the configuration file. It is possible to have multiple @@ -491,11 +465,9 @@ For full details of the options listed below, and their possible values, see .It CertificateFile .It ChallengeResponseAuthentication .It CheckHostIP -.It Cipher .It Ciphers .It ClearAllForwardings .It Compression -.It CompressionLevel .It ConnectionAttempts .It ConnectTimeout .It ControlMaster @@ -540,17 +512,15 @@ For full details of the options listed below, and their possible values, see .It PKCS11Provider .It Port .It PreferredAuthentications -.It Protocol .It ProxyCommand .It ProxyJump .It ProxyUseFdpass .It PubkeyAcceptedKeyTypes .It PubkeyAuthentication .It RekeyLimit +.It RemoteCommand .It RemoteForward .It RequestTTY -.It RhostsRSAAuthentication -.It RSAAuthentication .It SendEnv .It ServerAliveInterval .It ServerAliveCountMax @@ -622,21 +592,30 @@ Causes most warning and diagnostic messages to be suppressed. .Ar remote_socket : local_socket .Sm on .Xc +.It Fl R Xo +.Sm off +.Oo Ar bind_address : Oc +.Ar port +.Sm on +.Xc Specifies that connections to the given TCP port or Unix socket on the remote -(server) host are to be forwarded to the given host and port, or Unix socket, -on the local side. +(server) host are to be forwarded to the local side. +.Pp This works by allocating a socket to listen to either a TCP .Ar port or to a Unix socket on the remote side. Whenever a connection is made to this port or Unix socket, the connection is forwarded over the secure channel, and a connection -is made to either +is made from the local machine to either an explicit destination specified by .Ar host port .Ar hostport , or .Ar local_socket , -from the local machine. +or, if no explicit destination was specified, +.Nm +will act as a SOCKS 4/5 proxy and forward connections to the destinations +requested by the remote SOCKS client. .Pp Port forwardings can also be specified in the configuration file. Privileged ports can be forwarded only when @@ -806,21 +785,7 @@ a per-user configuration file and a system-wide configuration file. The file format and configuration options are described in .Xr ssh_config 5 . .Sh AUTHENTICATION -The OpenSSH SSH client supports SSH protocols 1 and 2. -The default is to use protocol 2 only, -though this can be changed via the -.Cm Protocol -option in -.Xr ssh_config 5 -or the -.Fl 1 -and -.Fl 2 -options (see above). -Protocol 1 should not be used -and is only offered to support legacy devices. -It suffers from a number of cryptographic weaknesses -and doesn't support many of the advanced features available for protocol 2. +The OpenSSH SSH client supports SSH protocol 2. .Pp The methods available for authentication are: GSSAPI-based authentication, @@ -890,11 +855,20 @@ The client proves that it has access to the private key and the server checks that the corresponding public key is authorized to accept the account. .Pp +The server may inform the client of errors that prevented public key +authentication from succeeding after authentication completes using a +different method. +These may be viewed by increasing the +.Cm LogLevel +to +.Cm DEBUG +or higher (e.g. by using the +.Fl v +flag). +.Pp The user creates his/her key pair by running .Xr ssh-keygen 1 . This stores the private key in -.Pa ~/.ssh/identity -(protocol 1), .Pa ~/.ssh/id_dsa (DSA), .Pa ~/.ssh/id_ecdsa @@ -905,8 +879,6 @@ or .Pa ~/.ssh/id_rsa (RSA) and stores the public key in -.Pa ~/.ssh/identity.pub -(protocol 1), .Pa ~/.ssh/id_dsa.pub (DSA), .Pa ~/.ssh/id_ecdsa.pub @@ -1490,7 +1462,6 @@ Contains additional definitions for environment variables; see .Sx ENVIRONMENT , above. .Pp -.It Pa ~/.ssh/identity .It Pa ~/.ssh/id_dsa .It Pa ~/.ssh/id_ecdsa .It Pa ~/.ssh/id_ed25519 @@ -1505,7 +1476,6 @@ It is possible to specify a passphrase when generating the key which will be used to encrypt the sensitive part of this file using 3DES. .Pp -.It Pa ~/.ssh/identity.pub .It Pa ~/.ssh/id_dsa.pub .It Pa ~/.ssh/id_ecdsa.pub .It Pa ~/.ssh/id_ed25519.pub diff --git a/ssh.c b/ssh.c index 32b27bbc2ce6..ae37432bd47e 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.451 2017/03/10 04:07:20 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.464 2017/09/21 19:16:53 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -81,7 +81,6 @@ #include "xmalloc.h" #include "ssh.h" -#include "ssh1.h" #include "ssh2.h" #include "canohost.h" #include "compat.h" @@ -198,7 +197,7 @@ static void usage(void) { fprintf(stderr, -"usage: ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n" +"usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n" " [-D [bind_address:]port] [-E log_file] [-e escape_char]\n" " [-F configfile] [-I pkcs11] [-i identity_file]\n" " [-J [user@]host[:port]] [-L address] [-l login_name] [-m mac_spec]\n" @@ -209,8 +208,7 @@ usage(void) exit(255); } -static int ssh_session(void); -static int ssh_session2(void); +static int ssh_session2(struct ssh *); static void load_public_identity_files(void); static void main_sigchld_handler(int); @@ -511,13 +509,13 @@ int main(int ac, char **av) { struct ssh *ssh = NULL; - int i, r, opt, exit_status, use_syslog, direct, config_test = 0; + int i, r, opt, exit_status, use_syslog, direct, timeout_ms; + int config_test = 0, opt_terminated = 0; char *p, *cp, *line, *argv0, buf[PATH_MAX], *host_arg, *logfile; char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; char cname[NI_MAXHOST], uidstr[32], *conn_hash_hex; struct stat st; struct passwd *pw; - int timeout_ms; extern int optind, optreset; extern char *optarg; struct Forward fwd; @@ -598,6 +596,14 @@ main(int ac, char **av) */ initialize_options(&options); + /* + * Prepare main ssh transport/connection structures + */ + if ((ssh = ssh_alloc_session_state()) == NULL) + fatal("Couldn't allocate session state"); + channel_init_channels(ssh); + active_state = ssh; /* XXX legacy API compat */ + /* Parse command-line arguments. */ host = NULL; use_syslog = 0; @@ -609,10 +615,10 @@ main(int ac, char **av) "ACD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { switch (opt) { case '1': - options.protocol = SSH_PROTO_1; + fatal("SSH protocol v.1 is no longer supported"); break; case '2': - options.protocol = SSH_PROTO_2; + /* Ignored */ break; case '4': options.address_family = AF_INET; @@ -690,11 +696,7 @@ main(int ac, char **av) else if (strcmp(optarg, "key-plain") == 0) cp = sshkey_alg_list(0, 1, 0, '\n'); else if (strcmp(optarg, "protocol-version") == 0) { -#ifdef WITH_SSH1 - cp = xstrdup("1\n2"); -#else cp = xstrdup("2"); -#endif } if (cp == NULL) fatal("Unsupported query \"%s\"", optarg); @@ -818,27 +820,14 @@ main(int ac, char **av) } break; case 'c': - if (ciphers_valid(*optarg == '+' ? + if (!ciphers_valid(*optarg == '+' ? optarg + 1 : optarg)) { - /* SSH2 only */ - free(options.ciphers); - options.ciphers = xstrdup(optarg); - options.cipher = SSH_CIPHER_INVALID; - break; - } - /* SSH1 only */ - options.cipher = cipher_number(optarg); - if (options.cipher == -1) { fprintf(stderr, "Unknown cipher type '%s'\n", optarg); exit(255); } - if (options.cipher == SSH_CIPHER_3DES) - options.ciphers = xstrdup("3des-cbc"); - else if (options.cipher == SSH_CIPHER_BLOWFISH) - options.ciphers = xstrdup("blowfish-cbc"); - else - options.ciphers = xstrdup(KEX_CLIENT_ENCRYPT); + free(options.ciphers); + options.ciphers = xstrdup(optarg); break; case 'm': if (mac_valid(optarg)) { @@ -879,7 +868,8 @@ main(int ac, char **av) break; case 'R': - if (parse_forward(&fwd, optarg, 0, 1)) { + if (parse_forward(&fwd, optarg, 0, 1) || + parse_forward(&fwd, optarg, 1, 1)) { add_remote_forward(&options, &fwd); } else { fprintf(stderr, @@ -936,6 +926,9 @@ main(int ac, char **av) } } + if (optind > 1 && strcmp(av[optind - 1], "--") == 0) + opt_terminated = 1; + ac -= optind; av += optind; @@ -950,7 +943,7 @@ main(int ac, char **av) host = xstrdup(++cp); } else host = xstrdup(*av); - if (ac > 1) { + if (ac > 1 && !opt_terminated) { optind = optreset = 1; goto again; } @@ -992,12 +985,6 @@ main(int ac, char **av) } } - /* Cannot fork to background if no command. */ - if (fork_after_authentication_flag && buffer_len(&command) == 0 && - !no_shell_flag) - fatal("Cannot fork into background without a command " - "to execute."); - /* * Initialize "log" output. Since we are the client all output * goes to stderr unless otherwise specified by -y or -E. @@ -1007,8 +994,11 @@ main(int ac, char **av) if (logfile != NULL) log_redirect_stderr_to(logfile); log_init(argv0, - options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, - SYSLOG_FACILITY_USER, !use_syslog); + options.log_level == SYSLOG_LEVEL_NOT_SET ? + SYSLOG_LEVEL_INFO : options.log_level, + options.log_facility == SYSLOG_FACILITY_NOT_SET ? + SYSLOG_FACILITY_USER : options.log_facility, + !use_syslog); if (debug_flag) logit("%s, %s", SSH_RELEASE, @@ -1127,7 +1117,7 @@ main(int ac, char **av) if (options.port == 0) options.port = default_ssh_port(); - channel_set_af(options.address_family); + channel_set_af(ssh, options.address_family); /* Tidy and check options */ if (options.host_key_alias != NULL) @@ -1149,15 +1139,24 @@ main(int ac, char **av) options.use_privileged_port = 0; #endif + if (buffer_len(&command) != 0 && options.remote_command != NULL) + fatal("Cannot execute command-line and remote command."); + + /* Cannot fork to background if no command. */ + if (fork_after_authentication_flag && buffer_len(&command) == 0 && + options.remote_command == NULL && !no_shell_flag) + fatal("Cannot fork into background without a command " + "to execute."); + /* reinit */ - log_init(argv0, options.log_level, SYSLOG_FACILITY_USER, !use_syslog); + log_init(argv0, options.log_level, options.log_facility, !use_syslog); if (options.request_tty == REQUEST_TTY_YES || options.request_tty == REQUEST_TTY_FORCE) tty_flag = 1; /* Allocate a tty by default if no command specified. */ - if (buffer_len(&command) == 0) + if (buffer_len(&command) == 0 && options.remote_command == NULL) tty_flag = options.request_tty != REQUEST_TTY_NO; /* Force no tty */ @@ -1213,6 +1212,27 @@ main(int ac, char **av) free(cp); } + if (options.remote_command != NULL) { + debug3("expanding RemoteCommand: %s", options.remote_command); + cp = options.remote_command; + options.remote_command = percent_expand(cp, + "C", conn_hash_hex, + "L", shorthost, + "d", pw->pw_dir, + "h", host, + "l", thishost, + "n", host_arg, + "p", portstr, + "r", options.user, + "u", pw->pw_name, + (char *)NULL); + debug3("expanded RemoteCommand: %s", options.remote_command); + free(cp); + buffer_append(&command, options.remote_command, + strlen(options.remote_command)); + + } + if (options.control_path != NULL) { cp = tilde_expand_filename(options.control_path, original_real_uid); @@ -1242,9 +1262,7 @@ main(int ac, char **av) if (options.control_path != NULL) { int sock; if ((sock = muxclient(options.control_path)) >= 0) { - packet_set_connection(sock, sock); - ssh = active_state; /* XXX */ - enable_compat20(); /* XXX */ + ssh_packet_set_connection(ssh, sock, sock); packet_set_mux(); goto skip_connect; } @@ -1264,7 +1282,7 @@ main(int ac, char **av) timeout_ms = options.connection_timeout * 1000; /* Open a connection to the remote host. */ - if (ssh_connect(host, addrs, &hostaddr, options.port, + if (ssh_connect(ssh, host, addrs, &hostaddr, options.port, options.address_family, options.connection_attempts, &timeout_ms, options.tcp_keep_alive, options.use_privileged_port) != 0) @@ -1292,19 +1310,14 @@ main(int ac, char **av) sensitive_data.nkeys = 0; sensitive_data.keys = NULL; sensitive_data.external_keysign = 0; - if (options.rhosts_rsa_authentication || - options.hostbased_authentication) { + if (options.hostbased_authentication) { sensitive_data.nkeys = 9; sensitive_data.keys = xcalloc(sensitive_data.nkeys, - sizeof(Key)); + sizeof(struct sshkey)); /* XXX */ for (i = 0; i < sensitive_data.nkeys; i++) sensitive_data.keys[i] = NULL; PRIV_START; -#if WITH_SSH1 - sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, - _PATH_HOST_KEY_FILE, "", NULL, NULL); -#endif #ifdef OPENSSL_HAS_ECC sensitive_data.keys[1] = key_load_private_cert(KEY_ECDSA, _PATH_HOST_ECDSA_KEY_FILE, "", NULL); @@ -1452,7 +1465,7 @@ main(int ac, char **av) } skip_connect: - exit_status = compat20 ? ssh_session2() : ssh_session(); + exit_status = ssh_session2(ssh); packet_close(); if (options.control_path != NULL && muxserver_sock != -1) @@ -1525,7 +1538,7 @@ fork_postauth(void) /* Callback for remote forward global requests */ static void -ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) +ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) { struct Forward *rfwd = (struct Forward *)ctxt; @@ -1543,10 +1556,10 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) logit("Allocated port %u for remote forward to %s:%d", rfwd->allocated_port, rfwd->connect_host, rfwd->connect_port); - channel_update_permitted_opens(rfwd->handle, - rfwd->allocated_port); + channel_update_permitted_opens(ssh, + rfwd->handle, rfwd->allocated_port); } else { - channel_update_permitted_opens(rfwd->handle, -1); + channel_update_permitted_opens(ssh, rfwd->handle, -1); } } @@ -1575,29 +1588,27 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) } static void -client_cleanup_stdio_fwd(int id, void *arg) +client_cleanup_stdio_fwd(struct ssh *ssh, int id, void *arg) { debug("stdio forwarding: done"); cleanup_exit(0); } static void -ssh_stdio_confirm(int id, int success, void *arg) +ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) { if (!success) fatal("stdio forwarding failed"); } static void -ssh_init_stdio_forwarding(void) +ssh_init_stdio_forwarding(struct ssh *ssh) { Channel *c; int in, out; if (options.stdio_forward_host == NULL) return; - if (!compat20) - fatal("stdio forwarding require Protocol 2"); debug3("%s: %s:%d", __func__, options.stdio_forward_host, options.stdio_forward_port); @@ -1605,15 +1616,15 @@ ssh_init_stdio_forwarding(void) if ((in = dup(STDIN_FILENO)) < 0 || (out = dup(STDOUT_FILENO)) < 0) fatal("channel_connect_stdio_fwd: dup() in/out failed"); - if ((c = channel_connect_stdio_fwd(options.stdio_forward_host, + if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host, options.stdio_forward_port, in, out)) == NULL) fatal("%s: channel_connect_stdio_fwd failed", __func__); - channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0); - channel_register_open_confirm(c->self, ssh_stdio_confirm, NULL); + channel_register_cleanup(ssh, c->self, client_cleanup_stdio_fwd, 0); + channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL); } static void -ssh_init_forwarding(void) +ssh_init_forwarding(struct ssh *ssh) { int success = 0; int i; @@ -1632,7 +1643,7 @@ ssh_init_forwarding(void) options.local_forwards[i].connect_path : options.local_forwards[i].connect_host, options.local_forwards[i].connect_port); - success += channel_setup_local_fwd_listener( + success += channel_setup_local_fwd_listener(ssh, &options.local_forwards[i], &options.fwd_opts); } if (i > 0 && success != i && options.exit_on_forward_failure) @@ -1654,7 +1665,7 @@ ssh_init_forwarding(void) options.remote_forwards[i].connect_host, options.remote_forwards[i].connect_port); options.remote_forwards[i].handle = - channel_request_remote_forwarding( + channel_request_remote_forwarding(ssh, &options.remote_forwards[i]); if (options.remote_forwards[i].handle < 0) { if (options.exit_on_forward_failure) @@ -1663,14 +1674,15 @@ ssh_init_forwarding(void) logit("Warning: Could not request remote " "forwarding."); } else { - client_register_global_confirm(ssh_confirm_remote_forward, + client_register_global_confirm( + ssh_confirm_remote_forward, &options.remote_forwards[i]); } } /* Initiate tunnel forwarding. */ if (options.tun_open != SSH_TUNMODE_NO) { - if (client_request_tun_fwd(options.tun_open, + if (client_request_tun_fwd(ssh, options.tun_open, options.tun_local, options.tun_remote) == -1) { if (options.exit_on_forward_failure) fatal("Could not request tunnel forwarding."); @@ -1696,174 +1708,8 @@ check_agent_present(void) } } -static int -ssh_session(void) -{ - int type; - int interactive = 0; - int have_tty = 0; - struct winsize ws; - char *cp; - const char *display; - char *proto = NULL, *data = NULL; - - /* Enable compression if requested. */ - if (options.compression) { - debug("Requesting compression at level %d.", - options.compression_level); - - if (options.compression_level < 1 || - options.compression_level > 9) - fatal("Compression level must be from 1 (fast) to " - "9 (slow, best)."); - - /* Send the request. */ - packet_start(SSH_CMSG_REQUEST_COMPRESSION); - packet_put_int(options.compression_level); - packet_send(); - packet_write_wait(); - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) - packet_start_compression(options.compression_level); - else if (type == SSH_SMSG_FAILURE) - logit("Warning: Remote host refused compression."); - else - packet_disconnect("Protocol error waiting for " - "compression response."); - } - /* Allocate a pseudo tty if appropriate. */ - if (tty_flag) { - debug("Requesting pty."); - - /* Start the packet. */ - packet_start(SSH_CMSG_REQUEST_PTY); - - /* Store TERM in the packet. There is no limit on the - length of the string. */ - cp = getenv("TERM"); - if (!cp) - cp = ""; - packet_put_cstring(cp); - - /* Store window size in the packet. */ - if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) - memset(&ws, 0, sizeof(ws)); - packet_put_int((u_int)ws.ws_row); - packet_put_int((u_int)ws.ws_col); - packet_put_int((u_int)ws.ws_xpixel); - packet_put_int((u_int)ws.ws_ypixel); - - /* Store tty modes in the packet. */ - tty_make_modes(fileno(stdin), NULL); - - /* Send the packet, and wait for it to leave. */ - packet_send(); - packet_write_wait(); - - /* Read response from the server. */ - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) { - interactive = 1; - have_tty = 1; - } else if (type == SSH_SMSG_FAILURE) - logit("Warning: Remote host failed or refused to " - "allocate a pseudo tty."); - else - packet_disconnect("Protocol error waiting for pty " - "request response."); - } - /* Request X11 forwarding if enabled and DISPLAY is set. */ - display = getenv("DISPLAY"); - if (display == NULL && options.forward_x11) - debug("X11 forwarding requested but DISPLAY not set"); - if (options.forward_x11 && client_x11_get_proto(display, - options.xauth_location, options.forward_x11_trusted, - options.forward_x11_timeout, &proto, &data) == 0) { - /* Request forwarding with authentication spoofing. */ - debug("Requesting X11 forwarding with authentication " - "spoofing."); - x11_request_forwarding_with_spoofing(0, display, proto, - data, 0); - /* Read response from the server. */ - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) { - interactive = 1; - } else if (type == SSH_SMSG_FAILURE) { - logit("Warning: Remote host denied X11 forwarding."); - } else { - packet_disconnect("Protocol error waiting for X11 " - "forwarding"); - } - } - /* Tell the packet module whether this is an interactive session. */ - packet_set_interactive(interactive, - options.ip_qos_interactive, options.ip_qos_bulk); - - /* Request authentication agent forwarding if appropriate. */ - check_agent_present(); - - if (options.forward_agent) { - debug("Requesting authentication agent forwarding."); - auth_request_forwarding(); - - /* Read response from the server. */ - type = packet_read(); - packet_check_eom(); - if (type != SSH_SMSG_SUCCESS) - logit("Warning: Remote host denied authentication agent forwarding."); - } - - /* Initiate port forwardings. */ - ssh_init_stdio_forwarding(); - ssh_init_forwarding(); - - /* Execute a local command */ - if (options.local_command != NULL && - options.permit_local_command) - ssh_local_cmd(options.local_command); - - /* - * If requested and we are not interested in replies to remote - * forwarding requests, then let ssh continue in the background. - */ - if (fork_after_authentication_flag) { - if (options.exit_on_forward_failure && - options.num_remote_forwards > 0) { - debug("deferring postauth fork until remote forward " - "confirmation received"); - } else - fork_postauth(); - } - - /* - * If a command was specified on the command line, execute the - * command now. Otherwise request the server to start a shell. - */ - if (buffer_len(&command) > 0) { - int len = buffer_len(&command); - if (len > 900) - len = 900; - debug("Sending command: %.*s", len, - (u_char *)buffer_ptr(&command)); - packet_start(SSH_CMSG_EXEC_CMD); - packet_put_string(buffer_ptr(&command), buffer_len(&command)); - packet_send(); - packet_write_wait(); - } else { - debug("Requesting shell."); - packet_start(SSH_CMSG_EXEC_SHELL); - packet_send(); - packet_write_wait(); - } - - /* Enter the interactive session. */ - return client_loop(have_tty, tty_flag ? - options.escape_char : SSH_ESCAPECHAR_NONE, 0); -} - -/* request pty/x11/agent/tcpfwd/shell for channel */ static void -ssh_session2_setup(int id, int success, void *arg) +ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg) { extern char **environ; const char *display; @@ -1876,15 +1722,15 @@ ssh_session2_setup(int id, int success, void *arg) display = getenv("DISPLAY"); if (display == NULL && options.forward_x11) debug("X11 forwarding requested but DISPLAY not set"); - if (options.forward_x11 && client_x11_get_proto(display, + if (options.forward_x11 && client_x11_get_proto(ssh, display, options.xauth_location, options.forward_x11_trusted, options.forward_x11_timeout, &proto, &data) == 0) { /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication " "spoofing."); - x11_request_forwarding_with_spoofing(id, display, proto, + x11_request_forwarding_with_spoofing(ssh, id, display, proto, data, 1); - client_expect_confirm(id, "X11 forwarding", CONFIRM_WARN); + client_expect_confirm(ssh, id, "X11 forwarding", CONFIRM_WARN); /* XXX exit_on_forward_failure */ interactive = 1; } @@ -1892,7 +1738,7 @@ ssh_session2_setup(int id, int success, void *arg) check_agent_present(); if (options.forward_agent) { debug("Requesting authentication agent forwarding."); - channel_request_start(id, "auth-agent-req@openssh.com", 0); + channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0); packet_send(); } @@ -1900,13 +1746,13 @@ ssh_session2_setup(int id, int success, void *arg) packet_set_interactive(interactive, options.ip_qos_interactive, options.ip_qos_bulk); - client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), + client_session2_setup(ssh, id, tty_flag, subsystem_flag, getenv("TERM"), NULL, fileno(stdin), &command, environ); } /* open new channel for a session */ static int -ssh_session2_open(void) +ssh_session2_open(struct ssh *ssh) { Channel *c; int window, packetmax, in, out, err; @@ -1936,34 +1782,34 @@ ssh_session2_open(void) window >>= 1; packetmax >>= 1; } - c = channel_new( + c = channel_new(ssh, "session", SSH_CHANNEL_OPENING, in, out, err, window, packetmax, CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); - debug3("ssh_session2_open: channel_new: %d", c->self); + debug3("%s: channel_new: %d", __func__, c->self); - channel_send_open(c->self); + channel_send_open(ssh, c->self); if (!no_shell_flag) - channel_register_open_confirm(c->self, + channel_register_open_confirm(ssh, c->self, ssh_session2_setup, NULL); return c->self; } static int -ssh_session2(void) +ssh_session2(struct ssh *ssh) { int id = -1; /* XXX should be pre-session */ if (!options.control_persist) - ssh_init_stdio_forwarding(); - ssh_init_forwarding(); + ssh_init_stdio_forwarding(ssh); + ssh_init_forwarding(ssh); /* Start listening for multiplex clients */ if (!packet_get_mux()) - muxserver_listen(); + muxserver_listen(ssh); /* * If we are in control persist mode and have a working mux listen @@ -1991,10 +1837,10 @@ ssh_session2(void) * stdio forward setup that we skipped earlier. */ if (options.control_persist && muxserver_sock == -1) - ssh_init_stdio_forwarding(); + ssh_init_stdio_forwarding(ssh); if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) - id = ssh_session2_open(); + id = ssh_session2_open(ssh); else { packet_set_interactive( options.control_master == SSHCTL_MASTER_NO, @@ -2029,7 +1875,7 @@ ssh_session2(void) fork_postauth(); } - return client_loop(tty_flag, tty_flag ? + return client_loop(ssh, tty_flag, tty_flag ? options.escape_char : SSH_ESCAPECHAR_NONE, id); } @@ -2039,16 +1885,16 @@ load_public_identity_files(void) { char *filename, *cp, thishost[NI_MAXHOST]; char *pwdir = NULL, *pwname = NULL; - Key *public; + struct sshkey *public; struct passwd *pw; int i; u_int n_ids, n_certs; char *identity_files[SSH_MAX_IDENTITY_FILES]; - Key *identity_keys[SSH_MAX_IDENTITY_FILES]; + struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES]; char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; #ifdef ENABLE_PKCS11 - Key **keys; + struct sshkey **keys; int nkeys; #endif /* PKCS11 */ diff --git a/ssh.h b/ssh.h index 50467a792bdf..12d80092250c 100644 --- a/ssh.h +++ b/ssh.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.h,v 1.83 2015/12/11 03:19:09 djm Exp $ */ +/* $OpenBSD: ssh.h,v 1.87 2017/05/07 23:15:59 djm Exp $ */ /* * Author: Tatu Ylonen @@ -32,7 +32,7 @@ /* * Maximum length of lines in authorized_keys file. - * Current value permits 16kbit RSA and RSA1 keys and 8kbit DSA keys, with + * Current value permits 16kbit RSA keys and 8kbit DSA keys, with * some room for options and comments. */ #define SSH_MAX_PUBKEY_BYTES 16384 @@ -47,7 +47,7 @@ #define PROTOCOL_MAJOR_1 1 #define PROTOCOL_MINOR_1 5 -/* We support both SSH1 and SSH2 */ +/* We support only SSH2 */ #define PROTOCOL_MAJOR_2 2 #define PROTOCOL_MINOR_2 0 @@ -98,8 +98,5 @@ #define SSH_PRIVSEP_USER "sshd" #endif -/* Minimum modulus size (n) for RSA keys. */ -#define SSH_RSA_MINIMUM_MODULUS_SIZE 768 - /* Listen backlog for sshd, ssh-agent and forwarding sockets */ #define SSH_LISTEN_BACKLOG 128 diff --git a/ssh1.h b/ssh1.h deleted file mode 100644 index 6a05c4724bb7..000000000000 --- a/ssh1.h +++ /dev/null @@ -1,91 +0,0 @@ -/* $OpenBSD: ssh1.h,v 1.7 2016/05/04 14:22:33 markus Exp $ */ - -/* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -/* - * Definition of message types. New values can be added, but old values - * should not be removed or without careful consideration of the consequences - * for compatibility. The maximum value is 254; value 255 is reserved for - * future extension. - */ -/* Ranges */ -#define SSH_MSG_MIN 1 -#define SSH_MSG_MAX 254 -/* Message name */ /* msg code */ /* arguments */ -#define SSH_MSG_DISCONNECT 1 /* cause (string) */ -#define SSH_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */ -#define SSH_CMSG_SESSION_KEY 3 /* key (BIGNUM) */ -#define SSH_CMSG_USER 4 /* user (string) */ -#define SSH_CMSG_AUTH_RHOSTS 5 /* user (string) */ -#define SSH_CMSG_AUTH_RSA 6 /* modulus (BIGNUM) */ -#define SSH_SMSG_AUTH_RSA_CHALLENGE 7 /* int (BIGNUM) */ -#define SSH_CMSG_AUTH_RSA_RESPONSE 8 /* int (BIGNUM) */ -#define SSH_CMSG_AUTH_PASSWORD 9 /* pass (string) */ -#define SSH_CMSG_REQUEST_PTY 10 /* TERM, tty modes */ -#define SSH_CMSG_WINDOW_SIZE 11 /* row,col,xpix,ypix */ -#define SSH_CMSG_EXEC_SHELL 12 /* */ -#define SSH_CMSG_EXEC_CMD 13 /* cmd (string) */ -#define SSH_SMSG_SUCCESS 14 /* */ -#define SSH_SMSG_FAILURE 15 /* */ -#define SSH_CMSG_STDIN_DATA 16 /* data (string) */ -#define SSH_SMSG_STDOUT_DATA 17 /* data (string) */ -#define SSH_SMSG_STDERR_DATA 18 /* data (string) */ -#define SSH_CMSG_EOF 19 /* */ -#define SSH_SMSG_EXITSTATUS 20 /* status (int) */ -#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21 /* channel (int) */ -#define SSH_MSG_CHANNEL_OPEN_FAILURE 22 /* channel (int) */ -#define SSH_MSG_CHANNEL_DATA 23 /* ch,data (int,str) */ -#define SSH_MSG_CHANNEL_CLOSE 24 /* channel (int) */ -#define SSH_MSG_CHANNEL_CLOSE_CONFIRMATION 25 /* channel (int) */ -/* SSH_CMSG_X11_REQUEST_FORWARDING 26 OBSOLETE */ -#define SSH_SMSG_X11_OPEN 27 /* channel (int) */ -#define SSH_CMSG_PORT_FORWARD_REQUEST 28 /* p,host,hp (i,s,i) */ -#define SSH_MSG_PORT_OPEN 29 /* ch,h,p (i,s,i) */ -#define SSH_CMSG_AGENT_REQUEST_FORWARDING 30 /* */ -#define SSH_SMSG_AGENT_OPEN 31 /* port (int) */ -#define SSH_MSG_IGNORE 32 /* string */ -#define SSH_CMSG_EXIT_CONFIRMATION 33 /* */ -#define SSH_CMSG_X11_REQUEST_FORWARDING 34 /* proto,data (s,s) */ -#define SSH_CMSG_AUTH_RHOSTS_RSA 35 /* user,mod (s,mpi) */ -#define SSH_MSG_DEBUG 36 /* string */ -#define SSH_CMSG_REQUEST_COMPRESSION 37 /* level 1-9 (int) */ -#define SSH_CMSG_MAX_PACKET_SIZE 38 /* size 4k-1024k (int) */ -#define SSH_CMSG_AUTH_TIS 39 /* we use this for s/key */ -#define SSH_SMSG_AUTH_TIS_CHALLENGE 40 /* challenge (string) */ -#define SSH_CMSG_AUTH_TIS_RESPONSE 41 /* response (string) */ -#define SSH_CMSG_AUTH_KERBEROS 42 /* (KTEXT) */ -#define SSH_SMSG_AUTH_KERBEROS_RESPONSE 43 /* (KTEXT) */ -#define SSH_CMSG_HAVE_KERBEROS_TGT 44 /* credentials (s) */ -#define SSH_CMSG_HAVE_AFS_TOKEN 65 /* token (s) */ - -/* protocol version 1.5 overloads some version 1.3 message types */ -#define SSH_MSG_CHANNEL_INPUT_EOF SSH_MSG_CHANNEL_CLOSE -#define SSH_MSG_CHANNEL_OUTPUT_CLOSE SSH_MSG_CHANNEL_CLOSE_CONFIRMATION - -/* - * Authentication methods. New types can be added, but old types should not - * be removed for compatibility. The maximum allowed value is 31. - */ -#define SSH_AUTH_RHOSTS 1 -#define SSH_AUTH_RSA 2 -#define SSH_AUTH_PASSWORD 3 -#define SSH_AUTH_RHOSTS_RSA 4 -#define SSH_AUTH_TIS 5 -#define SSH_AUTH_KERBEROS 6 -#define SSH_PASS_KERBEROS_TGT 7 - /* 8 to 15 are reserved */ -#define SSH_PASS_AFS_TOKEN 21 - -/* Protocol flags. These are bit masks. */ -#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes screen */ -#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN 2 /* forwarding opens contain host */ diff --git a/ssh_api.c b/ssh_api.c index 2a9f1497c75a..c84b4e713bf4 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.7 2016/05/04 14:22:33 markus Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.8 2017/04/30 23:13:25 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -371,7 +371,6 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp) } if (remote_major != 2) return SSH_ERR_PROTOCOL_MISMATCH; - enable_compat20(); chop(buf); debug("Remote version string %.100s", buf); if ((*bannerp = strdup(buf)) == NULL) diff --git a/ssh_config b/ssh_config index 90fb63f0bf43..c12f5ef52f48 100644 --- a/ssh_config +++ b/ssh_config @@ -1,4 +1,4 @@ -# $OpenBSD: ssh_config,v 1.30 2016/02/20 23:06:23 sobrado Exp $ +# $OpenBSD: ssh_config,v 1.33 2017/05/07 23:12:57 djm Exp $ # This is the ssh client system-wide configuration file. See # ssh_config(5) for more information. This file provides defaults for @@ -20,8 +20,6 @@ # Host * # ForwardAgent no # ForwardX11 no -# RhostsRSAAuthentication no -# RSAAuthentication yes # PasswordAuthentication yes # HostbasedAuthentication no # GSSAPIAuthentication no @@ -31,16 +29,14 @@ # AddressFamily any # ConnectTimeout 0 # StrictHostKeyChecking ask -# IdentityFile ~/.ssh/identity # IdentityFile ~/.ssh/id_rsa # IdentityFile ~/.ssh/id_dsa # IdentityFile ~/.ssh/id_ecdsa # IdentityFile ~/.ssh/id_ed25519 # Port 22 # Protocol 2 -# Cipher 3des -# Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc -# MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160 +# Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc +# MACs hmac-md5,hmac-sha1,umac-64@openssh.com # EscapeChar ~ # Tunnel no # TunnelDevice any:any diff --git a/ssh_config.0 b/ssh_config.0 index ade8e6562013..9493953ab187 100644 --- a/ssh_config.0 +++ b/ssh_config.0 @@ -3,10 +3,6 @@ SSH_CONFIG(5) File Formats Manual SSH_CONFIG(5) NAME ssh_config M-bM-^@M-^S OpenSSH SSH client configuration files -SYNOPSIS - ~/.ssh/config - /etc/ssh/ssh_config - DESCRIPTION ssh(1) obtains configuration data from the following sources in the following order: @@ -189,21 +185,14 @@ DESCRIPTION process, regardless of the setting of StrictHostKeyChecking. If the option is set to no, the check will not be executed. - Cipher Specifies the cipher to use for encrypting the session in - protocol version 1. Currently, blowfish, 3des (the default), and - des are supported, though des is only supported in the ssh(1) - client for interoperability with legacy protocol 1 - implementations; its use is strongly discouraged due to - cryptographic weaknesses. - Ciphers - Specifies the ciphers allowed for protocol version 2 in order of - preference. Multiple ciphers must be comma-separated. If the - specified value begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified - ciphers will be appended to the default set instead of replacing - them. If the specified value begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then - the specified ciphers (including wildcards) will be removed from - the default set instead of replacing them. + Specifies the ciphers allowed and their order of preference. + Multiple ciphers must be comma-separated. If the specified value + begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified ciphers will be + appended to the default set instead of replacing them. If the + specified value begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified + ciphers (including wildcards) will be removed from the default + set instead of replacing them. The supported ciphers are: @@ -216,11 +205,6 @@ DESCRIPTION aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com - arcfour - arcfour128 - arcfour256 - blowfish-cbc - cast128-cbc chacha20-poly1305@openssh.com The default is: @@ -245,13 +229,6 @@ DESCRIPTION Specifies whether to use compression. The argument must be yes or no (the default). - CompressionLevel - Specifies the compression level to use if compression is enabled. - The argument must be an integer from 1 (fast) to 9 (slow, best). - The default level is 6, which is good for most applications. The - meaning of the values is the same as in gzip(1). Note that this - option applies to protocol version 1 only. - ConnectionAttempts Specifies the number of tries (one per second) to make before exiting. The argument must be an integer. This may be useful in @@ -491,8 +468,9 @@ DESCRIPTION HostKeyAlias Specifies an alias that should be used instead of the real host name when looking up or saving the host key in the host key - database files. This option is useful for tunneling SSH - connections or for multiple servers running on a single host. + database files and when validating host certificates. This + option is useful for tunneling SSH connections or for multiple + servers running on a single host. HostName Specifies the real host name to log into. This can be used to @@ -526,9 +504,8 @@ DESCRIPTION IdentityFile Specifies a file from which the user's DSA, ECDSA, Ed25519 or RSA - authentication identity is read. The default is ~/.ssh/identity - for protocol version 1, and ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, - ~/.ssh/id_ed25519 and ~/.ssh/id_rsa for protocol version 2. + authentication identity is read. The default is ~/.ssh/id_dsa, + ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and ~/.ssh/id_rsa. Additionally, any identities represented by the authentication agent will be used for authentication unless IdentitiesOnly is set. If no certificates have been explicitly specified by @@ -573,13 +550,14 @@ DESCRIPTION IPQoS Specifies the IPv4 type-of-service or DSCP class for connections. Accepted values are af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3, cs4, cs5, cs6, - cs7, ef, lowdelay, throughput, reliability, or a numeric value. - This option may take one or two arguments, separated by - whitespace. If one argument is specified, it is used as the - packet class unconditionally. If two values are specified, the - first is automatically selected for interactive sessions and the - second for non-interactive sessions. The default is lowdelay for - interactive sessions and throughput for non-interactive sessions. + cs7, ef, lowdelay, throughput, reliability, a numeric value, or + none to use the operating system default. This option may take + one or two arguments, separated by whitespace. If one argument + is specified, it is used as the packet class unconditionally. If + two values are specified, the first is automatically selected for + interactive sessions and the second for non-interactive sessions. + The default is lowdelay for interactive sessions and throughput + for non-interactive sessions. KbdInteractiveAuthentication Specifies whether to use keyboard-interactive authentication. @@ -712,15 +690,6 @@ DESCRIPTION gssapi-with-mic,hostbased,publickey, keyboard-interactive,password - Protocol - Specifies the protocol versions ssh(1) should support in order of - preference. The possible values are 1 and 2. Multiple versions - must be comma-separated. When this option is set to 2,1 ssh will - try version 2 and fall back to version 1 if version 2 is not - available. The default is version 2. Protocol 1 suffers from a - number of cryptographic weaknesses and should not be used. It is - only offered to support legacy devices. - ProxyCommand Specifies the command to use to connect to the server. The command string extends to the end of the line, and is executed @@ -799,15 +768,29 @@ DESCRIPTION rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done. + RemoteCommand + Specifies a command to execute on the remote machine after + successfully connecting to the server. The command string + extends to the end of the line, and is executed with the user's + shell. Arguments to RemoteCommand accept the tokens described in + the TOKENS section. + RemoteForward Specifies that a TCP port on the remote machine be forwarded over - the secure channel to the specified host and port from the local - machine. The first argument must be [bind_address:]port and the - second argument must be host:hostport. IPv6 addresses can be - specified by enclosing addresses in square brackets. Multiple - forwardings may be specified, and additional forwardings can be - given on the command line. Privileged ports can be forwarded - only when logging in as root on the remote machine. + the secure channel. The remote port may either be fowarded to a + specified host and port from the local machine, or may act as a + SOCKS 4/5 proxy that allows a remote client to connect to + arbitrary destinations from the local machine. The first + argument must be [bind_address:]port If forwarding to a specific + destination then the second argument must be host:hostport, + otherwise if no destination argument is specified then the remote + forwarding will be established as a SOCKS proxy. + + IPv6 addresses can be specified by enclosing addresses in square + brackets. Multiple forwardings may be specified, and additional + forwardings can be given on the command line. Privileged ports + can be forwarded only when logging in as root on the remote + machine. If the port argument is 0, the listen port will be dynamically allocated on the server and reported to the client at run time. @@ -835,19 +818,6 @@ DESCRIPTION List (KRL) as generated by ssh-keygen(1). For more information on KRLs, see the KEY REVOCATION LISTS section in ssh-keygen(1). - RhostsRSAAuthentication - Specifies whether to try rhosts based authentication with RSA - host authentication. The argument must be yes or no (the - default). This option applies to protocol version 1 only and - requires ssh(1) to be setuid root. - - RSAAuthentication - Specifies whether to try RSA authentication. The argument to - this keyword must be yes (the default) or no. RSA authentication - will only be attempted if the identity file exists, or an - authentication agent is running. Note that this option applies - to protocol version 1 only. - SendEnv Specifies what variables from the local environ(7) should be sent to the server. The server must also support it, and the server @@ -916,14 +886,25 @@ DESCRIPTION protection against trojan horse attacks, though it can be annoying when the /etc/ssh/ssh_known_hosts file is poorly maintained or when connections to new hosts are frequently made. - This option forces the user to manually add all new hosts. If - this flag is set to no, ssh will automatically add new host keys - to the user known hosts files. If this flag is set to ask (the - default), new host keys will be added to the user known host - files only after the user has confirmed that is what they really - want to do, and ssh will refuse to connect to hosts whose host - key has changed. The host keys of known hosts will be verified - automatically in all cases. + This option forces the user to manually add all new hosts. + + If this flag is set to M-bM-^@M-^\accept-newM-bM-^@M-^] then ssh will automatically + add new host keys to the user known hosts files, but will not + permit connections to hosts with changed host keys. If this flag + is set to M-bM-^@M-^\noM-bM-^@M-^] or M-bM-^@M-^\offM-bM-^@M-^], ssh will automatically add new host keys + to the user known hosts files and allow connections to hosts with + changed hostkeys to proceed, subject to some restrictions. If + this flag is set to ask (the default), new host keys will be + added to the user known host files only after the user has + confirmed that is what they really want to do, and ssh will + refuse to connect to hosts whose host key has changed. The host + keys of known hosts will be verified automatically in all cases. + + SyslogFacility + Gives the facility code that is used when logging messages from + ssh(1). The possible values are: DAEMON, USER, AUTH, LOCAL0, + LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The + default is USER. TCPKeepAlive Specifies whether the system should send TCP keepalive messages @@ -973,9 +954,7 @@ DESCRIPTION UsePrivilegedPort Specifies whether to use a privileged port for outgoing connections. The argument must be yes or no (the default). If - set to yes, ssh(1) must be setuid root. Note that this option - must be set to yes for RhostsRSAAuthentication with older - servers. + set to yes, ssh(1) must be setuid root. User Specifies the user to log in as. This can be useful when a different user name is used on different machines. This saves @@ -1065,6 +1044,8 @@ TOKENS ProxyCommand accepts the tokens %%, %h, %p, and %r. + RemoteCommand accepts the tokens %%, %C, %d, %h, %l, %n, %p, %r, and %u. + FILES ~/.ssh/config This is the per-user configuration file. The format of this file @@ -1089,4 +1070,4 @@ AUTHORS created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. -OpenBSD 6.0 February 27, 2017 OpenBSD 6.0 +OpenBSD 6.2 September 21, 2017 OpenBSD 6.2 diff --git a/ssh_config.5 b/ssh_config.5 index 532745b2ff48..eab8dd01c22a 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -33,16 +33,13 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh_config.5,v 1.242 2017/02/27 14:30:33 jmc Exp $ -.Dd $Mdocdate: February 27 2017 $ +.\" $OpenBSD: ssh_config.5,v 1.256 2017/09/21 19:16:53 markus Exp $ +.Dd $Mdocdate: September 21 2017 $ .Dt SSH_CONFIG 5 .Os .Sh NAME .Nm ssh_config .Nd OpenSSH SSH client configuration files -.Sh SYNOPSIS -.Nm ~/.ssh/config -.Nm /etc/ssh/ssh_config .Sh DESCRIPTION .Xr ssh 1 obtains configuration data from the following sources in @@ -391,25 +388,8 @@ in the process, regardless of the setting of If the option is set to .Cm no , the check will not be executed. -.It Cm Cipher -Specifies the cipher to use for encrypting the session -in protocol version 1. -Currently, -.Cm blowfish , -.Cm 3des -(the default), -and -.Cm des -are supported, -though -.Cm des -is only supported in the -.Xr ssh 1 -client for interoperability with legacy protocol 1 implementations; -its use is strongly discouraged due to cryptographic weaknesses. .It Cm Ciphers -Specifies the ciphers allowed for protocol version 2 -in order of preference. +Specifies the ciphers allowed and their order of preference. Multiple ciphers must be comma-separated. If the specified value begins with a .Sq + @@ -431,11 +411,6 @@ aes192-ctr aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com -arcfour -arcfour128 -arcfour256 -blowfish-cbc -cast128-cbc chacha20-poly1305@openssh.com .Ed .Pp @@ -472,13 +447,6 @@ The argument must be or .Cm no (the default). -.It Cm CompressionLevel -Specifies the compression level to use if compression is enabled. -The argument must be an integer from 1 (fast) to 9 (slow, best). -The default level is 6, which is good for most applications. -The meaning of the values is the same as in -.Xr gzip 1 . -Note that this option applies to protocol version 1 only. .It Cm ConnectionAttempts Specifies the number of tries (one per second) to make before exiting. The argument must be an integer. @@ -838,7 +806,7 @@ The list of available key types may also be obtained using .It Cm HostKeyAlias Specifies an alias that should be used instead of the real host name when looking up or saving the host key -in the host key database files. +in the host key database files and when validating host certificates. This option is useful for tunneling SSH connections or for multiple servers running on a single host. .It Cm HostName @@ -902,14 +870,11 @@ section. Specifies a file from which the user's DSA, ECDSA, Ed25519 or RSA authentication identity is read. The default is -.Pa ~/.ssh/identity -for protocol version 1, and .Pa ~/.ssh/id_dsa , .Pa ~/.ssh/id_ecdsa , .Pa ~/.ssh/id_ed25519 and -.Pa ~/.ssh/id_rsa -for protocol version 2. +.Pa ~/.ssh/id_rsa . Additionally, any identities represented by the authentication agent will be used for authentication unless .Cm IdentitiesOnly @@ -1004,7 +969,9 @@ Accepted values are .Cm lowdelay , .Cm throughput , .Cm reliability , -or a numeric value. +a numeric value, or +.Cm none +to use the operating system default. This option may take one or two arguments, separated by whitespace. If one argument is specified, it is used as the packet class unconditionally. If two values are specified, the first is automatically selected for @@ -1192,21 +1159,6 @@ The default is: gssapi-with-mic,hostbased,publickey, keyboard-interactive,password .Ed -.It Cm Protocol -Specifies the protocol versions -.Xr ssh 1 -should support in order of preference. -The possible values are 1 and 2. -Multiple versions must be comma-separated. -When this option is set to -.Cm 2,1 -.Nm ssh -will try version 2 and fall back to version 1 -if version 2 is not available. -The default is version 2. -Protocol 1 suffers from a number of cryptographic weaknesses and should -not be used. -It is only offered to support legacy devices. .It Cm ProxyCommand Specifies the command to use to connect to the server. The command @@ -1334,15 +1286,31 @@ is .Cm default none , which means that rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done. +.It Cm RemoteCommand +Specifies a command to execute on the remote machine after successfully +connecting to the server. +The command string extends to the end of the line, and is executed with +the user's shell. +Arguments to +.Cm RemoteCommand +accept the tokens described in the +.Sx TOKENS +section. .It Cm RemoteForward Specifies that a TCP port on the remote machine be forwarded over -the secure channel to the specified host and port from the local machine. +the secure channel. +The remote port may either be fowarded to a specified host and port +from the local machine, or may act as a SOCKS 4/5 proxy that allows a remote +client to connect to arbitrary destinations from the local machine. The first argument must be .Sm off .Oo Ar bind_address : Oc Ar port .Sm on -and the second argument must be -.Ar host : Ns Ar hostport . +If forwarding to a specific destination then the second argument must be +.Ar host : Ns Ar hostport , +otherwise if no destination argument is specified then the remote forwarding +will be established as a SOCKS proxy. +.Pp IPv6 addresses can be specified by enclosing addresses in square brackets. Multiple forwardings may be specified, and additional forwardings can be given on the command line. @@ -1397,28 +1365,6 @@ an OpenSSH Key Revocation List (KRL) as generated by .Xr ssh-keygen 1 . For more information on KRLs, see the KEY REVOCATION LISTS section in .Xr ssh-keygen 1 . -.It Cm RhostsRSAAuthentication -Specifies whether to try rhosts based authentication with RSA host -authentication. -The argument must be -.Cm yes -or -.Cm no -(the default). -This option applies to protocol version 1 only and requires -.Xr ssh 1 -to be setuid root. -.It Cm RSAAuthentication -Specifies whether to try RSA authentication. -The argument to this keyword must be -.Cm yes -(the default) -or -.Cm no . -RSA authentication will only be -attempted if the identity file exists, or an authentication agent is -running. -Note that this option applies to protocol version 1 only. .It Cm SendEnv Specifies what variables from the local .Xr environ 7 @@ -1518,10 +1464,19 @@ file is poorly maintained or when connections to new hosts are frequently made. This option forces the user to manually add all new hosts. +.Pp If this flag is set to -.Cm no , -ssh will automatically add new host keys to the -user known hosts files. +.Dq accept-new +then ssh will automatically add new host keys to the user +known hosts files, but will not permit connections to hosts with +changed host keys. +If this flag is set to +.Dq no +or +.Dq off , +ssh will automatically add new host keys to the user known hosts files +and allow connections to hosts with changed hostkeys to proceed, +subject to some restrictions. If this flag is set to .Cm ask (the default), @@ -1531,6 +1486,12 @@ has confirmed that is what they really want to do, and ssh will refuse to connect to hosts whose host key has changed. The host keys of known hosts will be verified automatically in all cases. +.It Cm SyslogFacility +Gives the facility code that is used when logging messages from +.Xr ssh 1 . +The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, +LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. +The default is USER. .It Cm TCPKeepAlive Specifies whether the system should send TCP keepalive messages to the other side. @@ -1627,11 +1588,6 @@ If set to .Cm yes , .Xr ssh 1 must be setuid root. -Note that this option must be set to -.Cm yes -for -.Cm RhostsRSAAuthentication -with older servers. .It Cm User Specifies the user to log in as. This can be useful when a different user name is used on different machines. @@ -1770,6 +1726,9 @@ accepts the tokens %%, %C, %d, %h, %l, %n, %p, %r, and %u. .Pp .Cm ProxyCommand accepts the tokens %%, %h, %p, and %r. +.Pp +.Cm RemoteCommand +accepts the tokens %%, %C, %d, %h, %l, %n, %p, %r, and %u. .Sh FILES .Bl -tag -width Ds .It Pa ~/.ssh/config diff --git a/sshbuf-getput-basic.c b/sshbuf-getput-basic.c index 74c49be7cc62..50648258f48d 100644 --- a/sshbuf-getput-basic.c +++ b/sshbuf-getput-basic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf-getput-basic.c,v 1.6 2016/06/16 11:00:17 dtucker Exp $ */ +/* $OpenBSD: sshbuf-getput-basic.c,v 1.7 2017/06/01 04:51:58 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -365,7 +365,7 @@ sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len) int sshbuf_put_cstring(struct sshbuf *buf, const char *v) { - return sshbuf_put_string(buf, (u_char *)v, v == NULL ? 0 : strlen(v)); + return sshbuf_put_string(buf, v, v == NULL ? 0 : strlen(v)); } int diff --git a/sshbuf.c b/sshbuf.c index cbf7ed4a428f..de783a3638f8 100644 --- a/sshbuf.c +++ b/sshbuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf.c,v 1.8 2016/11/25 23:22:04 djm Exp $ */ +/* $OpenBSD: sshbuf.c,v 1.11 2017/06/01 06:58:25 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -193,15 +193,16 @@ sshbuf_reset(struct sshbuf *buf) buf->off = buf->size; return; } - if (sshbuf_check_sanity(buf) == 0) - explicit_bzero(buf->d, buf->alloc); + (void) sshbuf_check_sanity(buf); buf->off = buf->size = 0; if (buf->alloc != SSHBUF_SIZE_INIT) { - if ((d = realloc(buf->d, SSHBUF_SIZE_INIT)) != NULL) { + if ((d = recallocarray(buf->d, buf->alloc, SSHBUF_SIZE_INIT, + 1)) != NULL) { buf->cd = buf->d = d; buf->alloc = SSHBUF_SIZE_INIT; } } + explicit_bzero(buf->d, SSHBUF_SIZE_INIT); } size_t @@ -253,9 +254,8 @@ sshbuf_set_max_size(struct sshbuf *buf, size_t max_size) rlen = ROUNDUP(buf->size, SSHBUF_SIZE_INC); if (rlen > max_size) rlen = max_size; - explicit_bzero(buf->d + buf->size, buf->alloc - buf->size); SSHBUF_DBG(("new alloc = %zu", rlen)); - if ((dp = realloc(buf->d, rlen)) == NULL) + if ((dp = recallocarray(buf->d, buf->alloc, rlen, 1)) == NULL) return SSH_ERR_ALLOC_FAIL; buf->cd = buf->d = dp; buf->alloc = rlen; @@ -344,7 +344,7 @@ sshbuf_allocate(struct sshbuf *buf, size_t len) if (rlen > buf->max_size) rlen = buf->alloc + need; SSHBUF_DBG(("adjusted rlen %zu", rlen)); - if ((dp = realloc(buf->d, rlen)) == NULL) { + if ((dp = recallocarray(buf->d, buf->alloc, rlen, 1)) == NULL) { SSHBUF_DBG(("realloc fail")); return SSH_ERR_ALLOC_FAIL; } @@ -391,6 +391,9 @@ sshbuf_consume(struct sshbuf *buf, size_t len) if (len > sshbuf_len(buf)) return SSH_ERR_MESSAGE_INCOMPLETE; buf->off += len; + /* deal with empty buffer */ + if (buf->off == buf->size) + buf->off = buf->size = 0; SSHBUF_TELL("done"); return 0; } diff --git a/sshbuf.h b/sshbuf.h index 1ac4b8c0ac13..77f1e9e6d09a 100644 --- a/sshbuf.h +++ b/sshbuf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf.h,v 1.8 2016/11/25 23:22:04 djm Exp $ */ +/* $OpenBSD: sshbuf.h,v 1.9 2017/09/12 06:32:07 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -211,6 +211,7 @@ int sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, /* Another variant: "peeks" into the buffer without modifying it */ int sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp, size_t *lenp); +/* XXX peek_u8 / peek_u32 */ /* * Functions to extract or store SSH wire encoded bignums and elliptic diff --git a/sshconnect.c b/sshconnect.c index 948b638ad114..dc7a704d2a2d 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.273 2017/03/10 03:22:40 dtucker Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.287 2017/09/14 04:32:21 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -34,6 +34,9 @@ #include #endif #include +#ifdef HAVE_POLL_H +#include +#endif #include #include #include @@ -45,7 +48,6 @@ #include "key.h" #include "hostfile.h" #include "ssh.h" -#include "rsa.h" #include "buffer.h" #include "packet.h" #include "uidswap.h" @@ -67,7 +69,7 @@ char *client_version_string = NULL; char *server_version_string = NULL; -Key *previous_host_key = NULL; +struct sshkey *previous_host_key = NULL; static int matching_host_key_dns = 0; @@ -79,8 +81,8 @@ extern char *__progname; extern uid_t original_real_uid; extern uid_t original_effective_uid; -static int show_other_keys(struct hostkeys *, Key *); -static void warn_changed_key(Key *); +static int show_other_keys(struct hostkeys *, struct sshkey *); +static void warn_changed_key(struct sshkey *); /* Expand a proxy command */ static char * @@ -102,7 +104,7 @@ expand_proxy_command(const char *proxy_command, const char *user, * a connected fd back to us. */ static int -ssh_proxy_fdpass_connect(const char *host, u_short port, +ssh_proxy_fdpass_connect(struct ssh *ssh, const char *host, u_short port, const char *proxy_command) { char *command_string; @@ -173,7 +175,8 @@ ssh_proxy_fdpass_connect(const char *host, u_short port, fatal("Couldn't wait for child: %s", strerror(errno)); /* Set the connection file descriptors. */ - packet_set_connection(sock, sock); + if (ssh_packet_set_connection(ssh, sock, sock) == NULL) + return -1; /* ssh_packet_set_connection logs error */ return 0; } @@ -182,7 +185,8 @@ ssh_proxy_fdpass_connect(const char *host, u_short port, * Connect to the given ssh server using a proxy command. */ static int -ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) +ssh_proxy_connect(struct ssh *ssh, const char *host, u_short port, + const char *proxy_command) { char *command_string; int pin[2], pout[2]; @@ -249,9 +253,9 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) free(command_string); /* Set the connection file descriptors. */ - packet_set_connection(pout[0], pin[1]); + if (ssh_packet_set_connection(ssh, pout[0], pin[1]) == NULL) + return -1; /* ssh_packet_set_connection logs error */ - /* Indicate OK return */ return 0; } @@ -328,87 +332,71 @@ ssh_create_socket(int privileged, struct addrinfo *ai) return sock; } +/* + * Wait up to *timeoutp milliseconds for fd to be readable. Updates + * *timeoutp with time remaining. + * Returns 0 if fd ready or -1 on timeout or error (see errno). + */ +static int +waitrfd(int fd, int *timeoutp) +{ + struct pollfd pfd; + struct timeval t_start; + int oerrno, r; + + gettimeofday(&t_start, NULL); + pfd.fd = fd; + pfd.events = POLLIN; + for (; *timeoutp >= 0;) { + r = poll(&pfd, 1, *timeoutp); + oerrno = errno; + ms_subtract_diff(&t_start, timeoutp); + errno = oerrno; + if (r > 0) + return 0; + else if (r == -1 && errno != EAGAIN) + return -1; + else if (r == 0) + break; + } + /* timeout */ + errno = ETIMEDOUT; + return -1; +} + static int timeout_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen, int *timeoutp) { - fd_set *fdset; - struct timeval tv, t_start; - socklen_t optlen; - int optval, rc, result = -1; + int optval = 0; + socklen_t optlen = sizeof(optval); - gettimeofday(&t_start, NULL); - - if (*timeoutp <= 0) { - result = connect(sockfd, serv_addr, addrlen); - goto done; - } + /* No timeout: just do a blocking connect() */ + if (*timeoutp <= 0) + return connect(sockfd, serv_addr, addrlen); set_nonblock(sockfd); - rc = connect(sockfd, serv_addr, addrlen); - if (rc == 0) { + if (connect(sockfd, serv_addr, addrlen) == 0) { + /* Succeeded already? */ unset_nonblock(sockfd); - result = 0; - goto done; + return 0; + } else if (errno != EINPROGRESS) + return -1; + + if (waitrfd(sockfd, timeoutp) == -1) + return -1; + + /* Completed or failed */ + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) { + debug("getsockopt: %s", strerror(errno)); + return -1; } - if (errno != EINPROGRESS) { - result = -1; - goto done; + if (optval != 0) { + errno = optval; + return -1; } - - fdset = xcalloc(howmany(sockfd + 1, NFDBITS), - sizeof(fd_mask)); - FD_SET(sockfd, fdset); - ms_to_timeval(&tv, *timeoutp); - - for (;;) { - rc = select(sockfd + 1, NULL, fdset, NULL, &tv); - if (rc != -1 || errno != EINTR) - break; - } - - switch (rc) { - case 0: - /* Timed out */ - errno = ETIMEDOUT; - break; - case -1: - /* Select error */ - debug("select: %s", strerror(errno)); - break; - case 1: - /* Completed or failed */ - optval = 0; - optlen = sizeof(optval); - if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, - &optlen) == -1) { - debug("getsockopt: %s", strerror(errno)); - break; - } - if (optval != 0) { - errno = optval; - break; - } - result = 0; - unset_nonblock(sockfd); - break; - default: - /* Should not occur */ - fatal("Bogus return (%d) from select()", rc); - } - - free(fdset); - - done: - if (result == 0 && *timeoutp > 0) { - ms_subtract_diff(&t_start, timeoutp); - if (*timeoutp <= 0) { - errno = ETIMEDOUT; - result = -1; - } - } - - return (result); + unset_nonblock(sockfd); + return 0; } /* @@ -423,7 +411,7 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr, * the daemon. */ static int -ssh_connect_direct(const char *host, struct addrinfo *aitop, +ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop, struct sockaddr_storage *hostaddr, u_short port, int family, int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv) { @@ -497,40 +485,39 @@ ssh_connect_direct(const char *host, struct addrinfo *aitop, error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); /* Set the connection. */ - packet_set_connection(sock, sock); + if (ssh_packet_set_connection(ssh, sock, sock) == NULL) + return -1; /* ssh_packet_set_connection logs error */ - return 0; + return 0; } int -ssh_connect(const char *host, struct addrinfo *addrs, +ssh_connect(struct ssh *ssh, const char *host, struct addrinfo *addrs, struct sockaddr_storage *hostaddr, u_short port, int family, int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv) { if (options.proxy_command == NULL) { - return ssh_connect_direct(host, addrs, hostaddr, port, family, - connection_attempts, timeout_ms, want_keepalive, needpriv); + return ssh_connect_direct(ssh, host, addrs, hostaddr, port, + family, connection_attempts, timeout_ms, want_keepalive, + needpriv); } else if (strcmp(options.proxy_command, "-") == 0) { - packet_set_connection(STDIN_FILENO, STDOUT_FILENO); - return 0; /* Always succeeds */ + if ((ssh_packet_set_connection(ssh, + STDIN_FILENO, STDOUT_FILENO)) == NULL) + return -1; /* ssh_packet_set_connection logs error */ + return 0; } else if (options.proxy_use_fdpass) { - return ssh_proxy_fdpass_connect(host, port, + return ssh_proxy_fdpass_connect(ssh, host, port, options.proxy_command); } - return ssh_proxy_connect(host, port, options.proxy_command); + return ssh_proxy_connect(ssh, host, port, options.proxy_command); } static void send_client_banner(int connection_out, int minor1) { /* Send our own protocol version identification. */ - if (compat20) { - xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n", - PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION); - } else { - xasprintf(&client_version_string, "SSH-%d.%d-%.100s\n", - PROTOCOL_MAJOR_1, minor1, SSH_VERSION); - } + xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n", + PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION); if (atomicio(vwrite, connection_out, client_version_string, strlen(client_version_string)) != strlen(client_version_string)) fatal("write: %.100s", strerror(errno)); @@ -549,50 +536,27 @@ ssh_exchange_identification(int timeout_ms) int remote_major, remote_minor, mismatch; int connection_in = packet_get_connection_in(); int connection_out = packet_get_connection_out(); - int minor1 = PROTOCOL_MINOR_1, client_banner_sent = 0; u_int i, n; size_t len; - int fdsetsz, remaining, rc; - struct timeval t_start, t_remaining; - fd_set *fdset; + int rc; - fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask); - fdset = xcalloc(1, fdsetsz); - - /* - * If we are SSH2-only then we can send the banner immediately and - * save a round-trip. - */ - if (options.protocol == SSH_PROTO_2) { - enable_compat20(); - send_client_banner(connection_out, 0); - client_banner_sent = 1; - } + send_client_banner(connection_out, 0); /* Read other side's version identification. */ - remaining = timeout_ms; for (n = 0;;) { for (i = 0; i < sizeof(buf) - 1; i++) { if (timeout_ms > 0) { - gettimeofday(&t_start, NULL); - ms_to_timeval(&t_remaining, remaining); - FD_SET(connection_in, fdset); - rc = select(connection_in + 1, fdset, NULL, - fdset, &t_remaining); - ms_subtract_diff(&t_start, &remaining); - if (rc == 0 || remaining <= 0) + rc = waitrfd(connection_in, &timeout_ms); + if (rc == -1 && errno == ETIMEDOUT) { fatal("Connection timed out during " "banner exchange"); - if (rc == -1) { - if (errno == EINTR) - continue; - fatal("ssh_exchange_identification: " - "select: %s", strerror(errno)); + } else if (rc == -1) { + fatal("%s: %s", + __func__, strerror(errno)); } } len = atomicio(read, connection_in, &buf[i], 1); - if (len != 1 && errno == EPIPE) fatal("ssh_exchange_identification: " "Connection closed by remote host"); @@ -618,7 +582,6 @@ ssh_exchange_identification(int timeout_ms) debug("ssh_exchange_identification: %s", buf); } server_version_string = xstrdup(buf); - free(fdset); /* * Check that the versions match. In future this might accept @@ -634,51 +597,25 @@ ssh_exchange_identification(int timeout_ms) mismatch = 0; switch (remote_major) { - case 1: - if (remote_minor == 99 && - (options.protocol & SSH_PROTO_2) && - !(options.protocol & SSH_PROTO_1_PREFERRED)) { - enable_compat20(); - break; - } - if (!(options.protocol & SSH_PROTO_1)) { - mismatch = 1; - break; - } - if (remote_minor < 3) { - fatal("Remote machine has too old SSH software version."); - } else if (remote_minor == 3 || remote_minor == 4) { - /* We speak 1.3, too. */ - enable_compat13(); - minor1 = 3; - if (options.forward_agent) { - logit("Agent forwarding disabled for protocol 1.3"); - options.forward_agent = 0; - } - } - break; case 2: - if (options.protocol & SSH_PROTO_2) { - enable_compat20(); - break; - } - /* FALLTHROUGH */ + break; + case 1: + if (remote_minor != 99) + mismatch = 1; + break; default: mismatch = 1; break; } if (mismatch) fatal("Protocol major versions differ: %d vs. %d", - (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, - remote_major); + PROTOCOL_MAJOR_2, remote_major); if ((datafellows & SSH_BUG_DERIVEKEY) != 0) fatal("Server version \"%.100s\" uses unsafe key agreement; " "refusing connection", remote_version); if ((datafellows & SSH_BUG_RSASIGMD5) != 0) logit("Server version \"%.100s\" uses unsafe RSA signature " "scheme; disabling use of RSA keys", remote_version); - if (!client_banner_sent) - send_client_banner(connection_out, minor1); chop(server_version_string); } @@ -707,7 +644,7 @@ confirm(const char *prompt) } static int -check_host_cert(const char *host, const Key *host_key) +check_host_cert(const char *host, const struct sshkey *host_key) { const char *reason; @@ -805,13 +742,13 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr, #define ROQUIET 2 static int check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, - Key *host_key, int readonly, + struct sshkey *host_key, int readonly, char **user_hostfiles, u_int num_user_hostfiles, char **system_hostfiles, u_int num_system_hostfiles) { HostStatus host_status; HostStatus ip_status; - Key *raw_key = NULL; + struct sshkey *raw_key = NULL; char *ip = NULL, *host = NULL; char hostline[1000], *hostp, *fp, *ra; char msg[1024]; @@ -819,7 +756,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, const struct hostkey_entry *host_found, *ip_found; int len, cancelled_forwarding = 0; int local = sockaddr_is_local(hostaddr); - int r, want_cert = key_is_cert(host_key), host_ip_differ = 0; + int r, want_cert = sshkey_is_cert(host_key), host_ip_differ = 0; int hostkey_trusted = 0; /* Known or explicitly accepted by user */ struct hostkeys *host_hostkeys, *ip_hostkeys; u_int i; @@ -870,8 +807,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, retry: /* Reload these as they may have changed on cert->key downgrade */ - want_cert = key_is_cert(host_key); - type = key_type(host_key); + want_cert = sshkey_is_cert(host_key); + type = sshkey_type(host_key); /* * Check if the host key is present in the user's list of known @@ -891,7 +828,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, if (host_status == HOST_CHANGED && (ip_status != HOST_CHANGED || (ip_found != NULL && - !key_equal(ip_found->key, host_found->key)))) + !sshkey_equal(ip_found->key, host_found->key)))) host_ip_differ = 1; } else ip_status = host_status; @@ -903,7 +840,9 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, host, type, want_cert ? "certificate" : "key"); debug("Found %s in %s:%lu", want_cert ? "CA key" : "key", host_found->file, host_found->line); - if (want_cert && !check_host_cert(hostname, host_key)) + if (want_cert && + !check_host_cert(options.host_key_alias == NULL ? + hostname : options.host_key_alias, host_key)) goto fail; if (options.check_host_ip && ip_status == HOST_NEW) { if (readonly || want_cert) @@ -947,7 +886,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, if (readonly || want_cert) goto fail; /* The host is new. */ - if (options.strict_host_key_checking == 1) { + if (options.strict_host_key_checking == + SSH_STRICT_HOSTKEY_YES) { /* * User has requested strict host key checking. We * will not add the host key automatically. The only @@ -956,7 +896,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, error("No %s host key is known for %.200s and you " "have requested strict checking.", type, host); goto fail; - } else if (options.strict_host_key_checking == 2) { + } else if (options.strict_host_key_checking == + SSH_STRICT_HOSTKEY_ASK) { char msg1[1024], msg2[1024]; if (show_other_keys(host_hostkeys, host_key)) @@ -1000,8 +941,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, hostkey_trusted = 1; /* user explicitly confirmed */ } /* - * If not in strict mode, add the key automatically to the - * local known_hosts file. + * If in "new" or "off" strict mode, add the key automatically + * to the local known_hosts file. */ if (options.check_host_ip && ip_status == HOST_NEW) { snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); @@ -1043,7 +984,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, * If strict host key checking is in use, the user will have * to edit the key manually and we can only abort. */ - if (options.strict_host_key_checking) { + if (options.strict_host_key_checking != + SSH_STRICT_HOSTKEY_OFF) { error("%s host key for %.200s was revoked and you have " "requested strict checking.", type, host); goto fail; @@ -1088,14 +1030,16 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, warn_changed_key(host_key); error("Add correct host key in %.100s to get rid of this message.", user_hostfiles[0]); - error("Offending %s key in %s:%lu", key_type(host_found->key), + error("Offending %s key in %s:%lu", + sshkey_type(host_found->key), host_found->file, host_found->line); /* * If strict host key checking is in use, the user will have * to edit the key manually and we can only abort. */ - if (options.strict_host_key_checking) { + if (options.strict_host_key_checking != + SSH_STRICT_HOSTKEY_OFF) { error("%s host key for %.200s has changed and you have " "requested strict checking.", type, host); goto fail; @@ -1182,15 +1126,17 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, "\nMatching host key in %s:%lu", host_found->file, host_found->line); } - if (options.strict_host_key_checking == 1) { - logit("%s", msg); - error("Exiting, you have requested strict checking."); - goto fail; - } else if (options.strict_host_key_checking == 2) { + if (options.strict_host_key_checking == + SSH_STRICT_HOSTKEY_ASK) { strlcat(msg, "\nAre you sure you want " "to continue connecting (yes/no)? ", sizeof(msg)); if (!confirm(msg)) goto fail; + } else if (options.strict_host_key_checking != + SSH_STRICT_HOSTKEY_OFF) { + logit("%s", msg); + error("Exiting, you have requested strict checking."); + goto fail; } else { logit("%s", msg); } @@ -1217,14 +1163,16 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, * search normally. */ debug("No matching CA found. Retry with plain key"); - raw_key = key_from_private(host_key); - if (key_drop_cert(raw_key) != 0) - fatal("Couldn't drop certificate"); + if ((r = sshkey_from_private(host_key, &raw_key)) != 0) + fatal("%s: sshkey_from_private: %s", + __func__, ssh_err(r)); + if ((r = sshkey_drop_cert(raw_key)) != 0) + fatal("Couldn't drop certificate: %s", ssh_err(r)); host_key = raw_key; goto retry; } if (raw_key != NULL) - key_free(raw_key); + sshkey_free(raw_key); free(ip); free(host); if (host_hostkeys != NULL) @@ -1236,7 +1184,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, /* returns 0 if key verifies or -1 if key does NOT verify */ int -verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) +verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key) { u_int i; int r = -1, flags = 0; @@ -1272,8 +1220,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) host_key->cert->principals[i]); } } else { - debug("Server host key: %s %s", compat20 ? - sshkey_ssh_name(host_key) : sshkey_type(host_key), fp); + debug("Server host key: %s %s", sshkey_ssh_name(host_key), fp); } if (sshkey_equal(previous_host_key, host_key)) { @@ -1341,8 +1288,8 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) free(fp); free(cafp); if (r == 0 && host_key != NULL) { - key_free(previous_host_key); - previous_host_key = key_from_private(host_key); + sshkey_free(previous_host_key); + r = sshkey_from_private(host_key, &previous_host_key); } return r; @@ -1378,17 +1325,8 @@ ssh_login(Sensitive *sensitive, const char *orighost, /* key exchange */ /* authenticate user */ debug("Authenticating to %s:%d as '%s'", host, port, server_user); - if (compat20) { - ssh_kex2(host, hostaddr, port); - ssh_userauth2(local_user, server_user, host, sensitive); - } else { -#ifdef WITH_SSH1 - ssh_kex(host, hostaddr); - ssh_userauth1(local_user, server_user, host, sensitive); -#else - fatal("ssh1 is not supported"); -#endif - } + ssh_kex2(host, hostaddr, port); + ssh_userauth2(local_user, server_user, host, sensitive); free(local_user); } @@ -1412,10 +1350,9 @@ ssh_put_password(char *password) /* print all known host keys for a given host, but skip keys of given type */ static int -show_other_keys(struct hostkeys *hostkeys, Key *key) +show_other_keys(struct hostkeys *hostkeys, struct sshkey *key) { int type[] = { - KEY_RSA1, KEY_RSA, KEY_DSA, KEY_ECDSA, @@ -1453,7 +1390,7 @@ show_other_keys(struct hostkeys *hostkeys, Key *key) } static void -warn_changed_key(Key *host_key) +warn_changed_key(struct sshkey *host_key) { char *fp; @@ -1516,7 +1453,7 @@ ssh_local_cmd(const char *args) } void -maybe_add_key_to_agent(char *authfile, Key *private, char *comment, +maybe_add_key_to_agent(char *authfile, struct sshkey *private, char *comment, char *passphrase) { int auth_sock = -1, r; diff --git a/sshconnect.h b/sshconnect.h index cf1851a959b7..b5029e2347e0 100644 --- a/sshconnect.h +++ b/sshconnect.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.h,v 1.29 2015/11/15 22:26:49 jcs Exp $ */ +/* $OpenBSD: sshconnect.h,v 1.31 2017/09/12 06:32:07 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -26,14 +26,16 @@ typedef struct Sensitive Sensitive; struct Sensitive { - Key **keys; - int nkeys; - int external_keysign; + struct sshkey **keys; + int nkeys; + int external_keysign; }; struct addrinfo; -int ssh_connect(const char *, struct addrinfo *, struct sockaddr_storage *, - u_short, int, int, int *, int, int); +struct ssh; + +int ssh_connect(struct ssh *, const char *, struct addrinfo *, + struct sockaddr_storage *, u_short, int, int, int *, int, int); void ssh_kill_proxy_command(void); void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short, @@ -41,7 +43,7 @@ void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short, void ssh_exchange_identification(int); -int verify_host_key(char *, struct sockaddr *, Key *); +int verify_host_key(char *, struct sockaddr *, struct sshkey *); void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short, char **, char **); @@ -55,7 +57,7 @@ void ssh_userauth2(const char *, const char *, char *, Sensitive *); void ssh_put_password(char *); int ssh_local_cmd(const char *); -void maybe_add_key_to_agent(char *, Key *, char *, char *); +void maybe_add_key_to_agent(char *, struct sshkey *, char *, char *); /* * Macros to raise/lower permissions. diff --git a/sshconnect1.c b/sshconnect1.c deleted file mode 100644 index dc00b4cd04d7..000000000000 --- a/sshconnect1.c +++ /dev/null @@ -1,774 +0,0 @@ -/* $OpenBSD: sshconnect1.c,v 1.80 2017/03/10 03:53:11 dtucker Exp $ */ -/* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * Code to connect to a remote host, and to perform the client side of the - * login (authentication) dialog. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "includes.h" - -#ifdef WITH_SSH1 - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "xmalloc.h" -#include "ssh.h" -#include "ssh1.h" -#include "rsa.h" -#include "buffer.h" -#include "packet.h" -#include "key.h" -#include "cipher.h" -#include "kex.h" -#include "uidswap.h" -#include "log.h" -#include "misc.h" -#include "readconf.h" -#include "authfd.h" -#include "sshconnect.h" -#include "authfile.h" -#include "canohost.h" -#include "hostfile.h" -#include "auth.h" -#include "digest.h" -#include "ssherr.h" - -/* Session id for the current session. */ -u_char session_id[16]; -u_int supported_authentications = 0; - -extern Options options; -extern char *__progname; - -/* - * Checks if the user has an authentication agent, and if so, tries to - * authenticate using the agent. - */ -static int -try_agent_authentication(void) -{ - int r, type, agent_fd, ret = 0; - u_char response[16]; - size_t i; - BIGNUM *challenge; - struct ssh_identitylist *idlist = NULL; - - /* Get connection to the agent. */ - if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { - if (r != SSH_ERR_AGENT_NOT_PRESENT) - debug("%s: ssh_get_authentication_socket: %s", - __func__, ssh_err(r)); - return 0; - } - - if ((challenge = BN_new()) == NULL) - fatal("try_agent_authentication: BN_new failed"); - - /* Loop through identities served by the agent. */ - if ((r = ssh_fetch_identitylist(agent_fd, 1, &idlist)) != 0) { - if (r != SSH_ERR_AGENT_NO_IDENTITIES) - debug("%s: ssh_fetch_identitylist: %s", - __func__, ssh_err(r)); - goto out; - } - for (i = 0; i < idlist->nkeys; i++) { - /* Try this identity. */ - debug("Trying RSA authentication via agent with '%.100s'", - idlist->comments[i]); - - /* Tell the server that we are willing to authenticate using this key. */ - packet_start(SSH_CMSG_AUTH_RSA); - packet_put_bignum(idlist->keys[i]->rsa->n); - packet_send(); - packet_write_wait(); - - /* Wait for server's response. */ - type = packet_read(); - - /* The server sends failure if it doesn't like our key or - does not support RSA authentication. */ - if (type == SSH_SMSG_FAILURE) { - debug("Server refused our key."); - continue; - } - /* Otherwise it should have sent a challenge. */ - if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) - packet_disconnect("Protocol error during RSA authentication: %d", - type); - - packet_get_bignum(challenge); - packet_check_eom(); - - debug("Received RSA challenge from server."); - - /* Ask the agent to decrypt the challenge. */ - if ((r = ssh_decrypt_challenge(agent_fd, idlist->keys[i], - challenge, session_id, response)) != 0) { - /* - * The agent failed to authenticate this identifier - * although it advertised it supports this. Just - * return a wrong value. - */ - logit("Authentication agent failed to decrypt " - "challenge: %s", ssh_err(r)); - explicit_bzero(response, sizeof(response)); - } - debug("Sending response to RSA challenge."); - - /* Send the decrypted challenge back to the server. */ - packet_start(SSH_CMSG_AUTH_RSA_RESPONSE); - for (i = 0; i < 16; i++) - packet_put_char(response[i]); - packet_send(); - packet_write_wait(); - - /* Wait for response from the server. */ - type = packet_read(); - - /* - * The server returns success if it accepted the - * authentication. - */ - if (type == SSH_SMSG_SUCCESS) { - debug("RSA authentication accepted by server."); - ret = 1; - break; - } else if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error waiting RSA auth " - "response: %d", type); - } - if (ret != 1) - debug("RSA authentication using agent refused."); - out: - ssh_free_identitylist(idlist); - ssh_close_authentication_socket(agent_fd); - BN_clear_free(challenge); - return ret; -} - -/* - * Computes the proper response to a RSA challenge, and sends the response to - * the server. - */ -static void -respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv) -{ - u_char buf[32], response[16]; - struct ssh_digest_ctx *md; - int i, len; - - /* Decrypt the challenge using the private key. */ - /* XXX think about Bleichenbacher, too */ - if (rsa_private_decrypt(challenge, challenge, prv) != 0) - packet_disconnect( - "respond_to_rsa_challenge: rsa_private_decrypt failed"); - - /* Compute the response. */ - /* The response is MD5 of decrypted challenge plus session id. */ - len = BN_num_bytes(challenge); - if (len <= 0 || (u_int)len > sizeof(buf)) - packet_disconnect( - "respond_to_rsa_challenge: bad challenge length %d", len); - - memset(buf, 0, sizeof(buf)); - BN_bn2bin(challenge, buf + sizeof(buf) - len); - if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || - ssh_digest_update(md, buf, 32) < 0 || - ssh_digest_update(md, session_id, 16) < 0 || - ssh_digest_final(md, response, sizeof(response)) < 0) - fatal("%s: md5 failed", __func__); - ssh_digest_free(md); - - debug("Sending response to host key RSA challenge."); - - /* Send the response back to the server. */ - packet_start(SSH_CMSG_AUTH_RSA_RESPONSE); - for (i = 0; i < 16; i++) - packet_put_char(response[i]); - packet_send(); - packet_write_wait(); - - explicit_bzero(buf, sizeof(buf)); - explicit_bzero(response, sizeof(response)); - explicit_bzero(&md, sizeof(md)); -} - -/* - * Checks if the user has authentication file, and if so, tries to authenticate - * the user using it. - */ -static int -try_rsa_authentication(int idx) -{ - BIGNUM *challenge; - Key *public, *private; - char buf[300], *passphrase = NULL, *comment, *authfile; - int i, perm_ok = 1, type, quit; - - public = options.identity_keys[idx]; - authfile = options.identity_files[idx]; - comment = xstrdup(authfile); - - debug("Trying RSA authentication with key '%.100s'", comment); - - /* Tell the server that we are willing to authenticate using this key. */ - packet_start(SSH_CMSG_AUTH_RSA); - packet_put_bignum(public->rsa->n); - packet_send(); - packet_write_wait(); - - /* Wait for server's response. */ - type = packet_read(); - - /* - * The server responds with failure if it doesn't like our key or - * doesn't support RSA authentication. - */ - if (type == SSH_SMSG_FAILURE) { - debug("Server refused our key."); - free(comment); - return 0; - } - /* Otherwise, the server should respond with a challenge. */ - if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) - packet_disconnect("Protocol error during RSA authentication: %d", type); - - /* Get the challenge from the packet. */ - if ((challenge = BN_new()) == NULL) - fatal("try_rsa_authentication: BN_new failed"); - packet_get_bignum(challenge); - packet_check_eom(); - - debug("Received RSA challenge from server."); - - /* - * If the key is not stored in external hardware, we have to - * load the private key. Try first with empty passphrase; if it - * fails, ask for a passphrase. - */ - if (public->flags & SSHKEY_FLAG_EXT) - private = public; - else - private = key_load_private_type(KEY_RSA1, authfile, "", NULL, - &perm_ok); - if (private == NULL && !options.batch_mode && perm_ok) { - snprintf(buf, sizeof(buf), - "Enter passphrase for RSA key '%.100s': ", comment); - for (i = 0; i < options.number_of_password_prompts; i++) { - passphrase = read_passphrase(buf, 0); - if (strcmp(passphrase, "") != 0) { - private = key_load_private_type(KEY_RSA1, - authfile, passphrase, NULL, NULL); - quit = 0; - } else { - debug2("no passphrase given, try next key"); - quit = 1; - } - if (private != NULL || quit) - break; - debug2("bad passphrase given, try again..."); - } - } - - if (private != NULL) - maybe_add_key_to_agent(authfile, private, comment, passphrase); - - if (passphrase != NULL) { - explicit_bzero(passphrase, strlen(passphrase)); - free(passphrase); - } - - /* We no longer need the comment. */ - free(comment); - - if (private == NULL) { - if (!options.batch_mode && perm_ok) - error("Bad passphrase."); - - /* Send a dummy response packet to avoid protocol error. */ - packet_start(SSH_CMSG_AUTH_RSA_RESPONSE); - for (i = 0; i < 16; i++) - packet_put_char(0); - packet_send(); - packet_write_wait(); - - /* Expect the server to reject it... */ - packet_read_expect(SSH_SMSG_FAILURE); - BN_clear_free(challenge); - return 0; - } - - /* Compute and send a response to the challenge. */ - respond_to_rsa_challenge(challenge, private->rsa); - - /* Destroy the private key unless it in external hardware. */ - if (!(private->flags & SSHKEY_FLAG_EXT)) - key_free(private); - - /* We no longer need the challenge. */ - BN_clear_free(challenge); - - /* Wait for response from the server. */ - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) { - debug("RSA authentication accepted by server."); - return 1; - } - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error waiting RSA auth response: %d", type); - debug("RSA authentication refused."); - return 0; -} - -/* - * Tries to authenticate the user using combined rhosts or /etc/hosts.equiv - * authentication and RSA host authentication. - */ -static int -try_rhosts_rsa_authentication(const char *local_user, Key * host_key) -{ - int type; - BIGNUM *challenge; - - debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication."); - - /* Tell the server that we are willing to authenticate using this key. */ - packet_start(SSH_CMSG_AUTH_RHOSTS_RSA); - packet_put_cstring(local_user); - packet_put_int(BN_num_bits(host_key->rsa->n)); - packet_put_bignum(host_key->rsa->e); - packet_put_bignum(host_key->rsa->n); - packet_send(); - packet_write_wait(); - - /* Wait for server's response. */ - type = packet_read(); - - /* The server responds with failure if it doesn't admit our - .rhosts authentication or doesn't know our host key. */ - if (type == SSH_SMSG_FAILURE) { - debug("Server refused our rhosts authentication or host key."); - return 0; - } - /* Otherwise, the server should respond with a challenge. */ - if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) - packet_disconnect("Protocol error during RSA authentication: %d", type); - - /* Get the challenge from the packet. */ - if ((challenge = BN_new()) == NULL) - fatal("try_rhosts_rsa_authentication: BN_new failed"); - packet_get_bignum(challenge); - packet_check_eom(); - - debug("Received RSA challenge for host key from server."); - - /* Compute a response to the challenge. */ - respond_to_rsa_challenge(challenge, host_key->rsa); - - /* We no longer need the challenge. */ - BN_clear_free(challenge); - - /* Wait for response from the server. */ - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) { - debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server."); - return 1; - } - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error waiting RSA auth response: %d", type); - debug("Rhosts or /etc/hosts.equiv with RSA host authentication refused."); - return 0; -} - -/* - * Tries to authenticate with any string-based challenge/response system. - * Note that the client code is not tied to s/key or TIS. - */ -static int -try_challenge_response_authentication(void) -{ - int type, i; - u_int clen; - char prompt[1024]; - char *challenge, *response; - - debug("Doing challenge response authentication."); - - for (i = 0; i < options.number_of_password_prompts; i++) { - /* request a challenge */ - packet_start(SSH_CMSG_AUTH_TIS); - packet_send(); - packet_write_wait(); - - type = packet_read(); - if (type != SSH_SMSG_FAILURE && - type != SSH_SMSG_AUTH_TIS_CHALLENGE) { - packet_disconnect("Protocol error: got %d in response " - "to SSH_CMSG_AUTH_TIS", type); - } - if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) { - debug("No challenge."); - return 0; - } - challenge = packet_get_string(&clen); - packet_check_eom(); - snprintf(prompt, sizeof prompt, "%s%s", challenge, - strchr(challenge, '\n') ? "" : "\nResponse: "); - free(challenge); - if (i != 0) - error("Permission denied, please try again."); - if (options.cipher == SSH_CIPHER_NONE) - logit("WARNING: Encryption is disabled! " - "Response will be transmitted in clear text."); - response = read_passphrase(prompt, 0); - if (strcmp(response, "") == 0) { - free(response); - break; - } - packet_start(SSH_CMSG_AUTH_TIS_RESPONSE); - ssh_put_password(response); - explicit_bzero(response, strlen(response)); - free(response); - packet_send(); - packet_write_wait(); - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) - return 1; - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response " - "to SSH_CMSG_AUTH_TIS_RESPONSE", type); - } - /* failure */ - return 0; -} - -/* - * Tries to authenticate with plain passwd authentication. - */ -static int -try_password_authentication(char *prompt) -{ - int type, i; - char *password; - - debug("Doing password authentication."); - if (options.cipher == SSH_CIPHER_NONE) - logit("WARNING: Encryption is disabled! Password will be transmitted in clear text."); - for (i = 0; i < options.number_of_password_prompts; i++) { - if (i != 0) - error("Permission denied, please try again."); - password = read_passphrase(prompt, 0); - packet_start(SSH_CMSG_AUTH_PASSWORD); - ssh_put_password(password); - explicit_bzero(password, strlen(password)); - free(password); - packet_send(); - packet_write_wait(); - - type = packet_read(); - if (type == SSH_SMSG_SUCCESS) - return 1; - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response to passwd auth", type); - } - /* failure */ - return 0; -} - -/* - * SSH1 key exchange - */ -void -ssh_kex(char *host, struct sockaddr *hostaddr) -{ - int i; - BIGNUM *key; - Key *host_key, *server_key; - int bits, rbits; - int ssh_cipher_default = SSH_CIPHER_3DES; - u_char session_key[SSH_SESSION_KEY_LENGTH]; - u_char cookie[8]; - u_int supported_ciphers; - u_int server_flags, client_flags; - - debug("Waiting for server public key."); - - /* Wait for a public key packet from the server. */ - packet_read_expect(SSH_SMSG_PUBLIC_KEY); - - /* Get cookie from the packet. */ - for (i = 0; i < 8; i++) - cookie[i] = packet_get_char(); - - /* Get the public key. */ - if ((server_key = key_new(KEY_RSA1)) == NULL) - fatal("%s: key_new(KEY_RSA1) failed", __func__); - bits = packet_get_int(); - packet_get_bignum(server_key->rsa->e); - packet_get_bignum(server_key->rsa->n); - - rbits = BN_num_bits(server_key->rsa->n); - if (bits != rbits) { - logit("Warning: Server lies about size of server public key: " - "actual size is %d bits vs. announced %d.", rbits, bits); - logit("Warning: This may be due to an old implementation of ssh."); - } - /* Get the host key. */ - if ((host_key = key_new(KEY_RSA1)) == NULL) - fatal("%s: key_new(KEY_RSA1) failed", __func__); - bits = packet_get_int(); - packet_get_bignum(host_key->rsa->e); - packet_get_bignum(host_key->rsa->n); - - rbits = BN_num_bits(host_key->rsa->n); - if (bits != rbits) { - logit("Warning: Server lies about size of server host key: " - "actual size is %d bits vs. announced %d.", rbits, bits); - logit("Warning: This may be due to an old implementation of ssh."); - } - - /* Get protocol flags. */ - server_flags = packet_get_int(); - packet_set_protocol_flags(server_flags); - - supported_ciphers = packet_get_int(); - supported_authentications = packet_get_int(); - packet_check_eom(); - - debug("Received server public key (%d bits) and host key (%d bits).", - BN_num_bits(server_key->rsa->n), BN_num_bits(host_key->rsa->n)); - - if (verify_host_key(host, hostaddr, host_key) == -1) - fatal("Host key verification failed."); - - client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN; - - derive_ssh1_session_id(host_key->rsa->n, server_key->rsa->n, cookie, session_id); - - /* - * Generate an encryption key for the session. The key is a 256 bit - * random number, interpreted as a 32-byte key, with the least - * significant 8 bits being the first byte of the key. - */ - arc4random_buf(session_key, sizeof(session_key)); - - /* - * According to the protocol spec, the first byte of the session key - * is the highest byte of the integer. The session key is xored with - * the first 16 bytes of the session id. - */ - if ((key = BN_new()) == NULL) - fatal("ssh_kex: BN_new failed"); - if (BN_set_word(key, 0) == 0) - fatal("ssh_kex: BN_set_word failed"); - for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) { - if (BN_lshift(key, key, 8) == 0) - fatal("ssh_kex: BN_lshift failed"); - if (i < 16) { - if (BN_add_word(key, session_key[i] ^ session_id[i]) - == 0) - fatal("ssh_kex: BN_add_word failed"); - } else { - if (BN_add_word(key, session_key[i]) == 0) - fatal("ssh_kex: BN_add_word failed"); - } - } - - /* - * Encrypt the integer using the public key and host key of the - * server (key with smaller modulus first). - */ - if (BN_cmp(server_key->rsa->n, host_key->rsa->n) < 0) { - /* Public key has smaller modulus. */ - if (BN_num_bits(host_key->rsa->n) < - BN_num_bits(server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { - fatal("respond_to_rsa_challenge: host_key %d < server_key %d + " - "SSH_KEY_BITS_RESERVED %d", - BN_num_bits(host_key->rsa->n), - BN_num_bits(server_key->rsa->n), - SSH_KEY_BITS_RESERVED); - } - if (rsa_public_encrypt(key, key, server_key->rsa) != 0 || - rsa_public_encrypt(key, key, host_key->rsa) != 0) - fatal("%s: rsa_public_encrypt failed", __func__); - } else { - /* Host key has smaller modulus (or they are equal). */ - if (BN_num_bits(server_key->rsa->n) < - BN_num_bits(host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { - fatal("respond_to_rsa_challenge: server_key %d < host_key %d + " - "SSH_KEY_BITS_RESERVED %d", - BN_num_bits(server_key->rsa->n), - BN_num_bits(host_key->rsa->n), - SSH_KEY_BITS_RESERVED); - } - if (rsa_public_encrypt(key, key, host_key->rsa) != 0 || - rsa_public_encrypt(key, key, server_key->rsa) != 0) - fatal("%s: rsa_public_encrypt failed", __func__); - } - - /* Destroy the public keys since we no longer need them. */ - key_free(server_key); - key_free(host_key); - - if (options.cipher == SSH_CIPHER_NOT_SET) { - if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default)) - options.cipher = ssh_cipher_default; - } else if (options.cipher == SSH_CIPHER_INVALID || - !(cipher_mask_ssh1(1) & (1 << options.cipher))) { - logit("No valid SSH1 cipher, using %.100s instead.", - cipher_name(ssh_cipher_default)); - options.cipher = ssh_cipher_default; - } - /* Check that the selected cipher is supported. */ - if (!(supported_ciphers & (1 << options.cipher))) - fatal("Selected cipher type %.100s not supported by server.", - cipher_name(options.cipher)); - - debug("Encryption type: %.100s", cipher_name(options.cipher)); - - /* Send the encrypted session key to the server. */ - packet_start(SSH_CMSG_SESSION_KEY); - packet_put_char(options.cipher); - - /* Send the cookie back to the server. */ - for (i = 0; i < 8; i++) - packet_put_char(cookie[i]); - - /* Send and destroy the encrypted encryption key integer. */ - packet_put_bignum(key); - BN_clear_free(key); - - /* Send protocol flags. */ - packet_put_int(client_flags); - - /* Send the packet now. */ - packet_send(); - packet_write_wait(); - - debug("Sent encrypted session key."); - - /* Set the encryption key. */ - packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, options.cipher); - - /* - * We will no longer need the session key here. - * Destroy any extra copies. - */ - explicit_bzero(session_key, sizeof(session_key)); - - /* - * Expect a success message from the server. Note that this message - * will be received in encrypted form. - */ - packet_read_expect(SSH_SMSG_SUCCESS); - - debug("Received encrypted confirmation."); -} - -/* - * Authenticate user - */ -void -ssh_userauth1(const char *local_user, const char *server_user, char *host, - Sensitive *sensitive) -{ - int i, type; - - if (supported_authentications == 0) - fatal("ssh_userauth1: server supports no auth methods"); - - /* Send the name of the user to log in as on the server. */ - packet_start(SSH_CMSG_USER); - packet_put_cstring(server_user); - packet_send(); - packet_write_wait(); - - /* - * The server should respond with success if no authentication is - * needed (the user has no password). Otherwise the server responds - * with failure. - */ - type = packet_read(); - - /* check whether the connection was accepted without authentication. */ - if (type == SSH_SMSG_SUCCESS) - goto success; - if (type != SSH_SMSG_FAILURE) - packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", type); - - /* - * Try .rhosts or /etc/hosts.equiv authentication with RSA host - * authentication. - */ - if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) && - options.rhosts_rsa_authentication) { - for (i = 0; i < sensitive->nkeys; i++) { - if (sensitive->keys[i] != NULL && - sensitive->keys[i]->type == KEY_RSA1 && - try_rhosts_rsa_authentication(local_user, - sensitive->keys[i])) - goto success; - } - } - /* Try RSA authentication if the server supports it. */ - if ((supported_authentications & (1 << SSH_AUTH_RSA)) && - options.rsa_authentication) { - /* - * Try RSA authentication using the authentication agent. The - * agent is tried first because no passphrase is needed for - * it, whereas identity files may require passphrases. - */ - if (try_agent_authentication()) - goto success; - - /* Try RSA authentication for each identity. */ - for (i = 0; i < options.num_identity_files; i++) - if (options.identity_keys[i] != NULL && - options.identity_keys[i]->type == KEY_RSA1 && - try_rsa_authentication(i)) - goto success; - } - /* Try challenge response authentication if the server supports it. */ - if ((supported_authentications & (1 << SSH_AUTH_TIS)) && - options.challenge_response_authentication && !options.batch_mode) { - if (try_challenge_response_authentication()) - goto success; - } - /* Try password authentication if the server supports it. */ - if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) && - options.password_authentication && !options.batch_mode) { - char prompt[80]; - - snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ", - server_user, host); - if (try_password_authentication(prompt)) - goto success; - } - /* All authentication methods have failed. Exit with an error message. */ - fatal("Permission denied."); - /* NOTREACHED */ - - success: - return; /* need statement after label */ -} - -#endif /* WITH_SSH1 */ diff --git a/sshconnect2.c b/sshconnect2.c index f8a54beea949..be9397e481bd 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.255 2017/03/11 23:40:26 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.266 2017/08/27 00:38:41 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -93,7 +93,7 @@ char *xxx_host; struct sockaddr *xxx_hostaddr; static int -verify_host_key_callback(Key *hostkey, struct ssh *ssh) +verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) { if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1) fatal("Host key verification failed."); @@ -217,7 +217,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) kex->server_version_string=server_version_string; kex->verify_host_key=&verify_host_key_callback; - dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); + ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); /* remove ext-info from the KEX proposals for rekeying */ myproposal[PROPOSAL_KEX_ALGS] = @@ -287,16 +287,16 @@ struct cauthmethod { int *batch_flag; /* flag in option struct that disables method */ }; -int input_userauth_service_accept(int, u_int32_t, void *); -int input_userauth_ext_info(int, u_int32_t, void *); -int input_userauth_success(int, u_int32_t, void *); -int input_userauth_success_unexpected(int, u_int32_t, void *); -int input_userauth_failure(int, u_int32_t, void *); -int input_userauth_banner(int, u_int32_t, void *); -int input_userauth_error(int, u_int32_t, void *); -int input_userauth_info_req(int, u_int32_t, void *); -int input_userauth_pk_ok(int, u_int32_t, void *); -int input_userauth_passwd_changereq(int, u_int32_t, void *); +int input_userauth_service_accept(int, u_int32_t, struct ssh *); +int input_userauth_ext_info(int, u_int32_t, struct ssh *); +int input_userauth_success(int, u_int32_t, struct ssh *); +int input_userauth_success_unexpected(int, u_int32_t, struct ssh *); +int input_userauth_failure(int, u_int32_t, struct ssh *); +int input_userauth_banner(int, u_int32_t, struct ssh *); +int input_userauth_error(int, u_int32_t, struct ssh *); +int input_userauth_info_req(int, u_int32_t, struct ssh *); +int input_userauth_pk_ok(int, u_int32_t, struct ssh *); +int input_userauth_passwd_changereq(int, u_int32_t, struct ssh *); int userauth_none(Authctxt *); int userauth_pubkey(Authctxt *); @@ -306,11 +306,11 @@ int userauth_hostbased(Authctxt *); #ifdef GSSAPI int userauth_gssapi(Authctxt *authctxt); -int input_gssapi_response(int type, u_int32_t, void *); -int input_gssapi_token(int type, u_int32_t, void *); -int input_gssapi_hash(int type, u_int32_t, void *); -int input_gssapi_error(int, u_int32_t, void *); -int input_gssapi_errtok(int, u_int32_t, void *); +int input_gssapi_response(int type, u_int32_t, struct ssh *); +int input_gssapi_token(int type, u_int32_t, struct ssh *); +int input_gssapi_hash(int type, u_int32_t, struct ssh *); +int input_gssapi_error(int, u_int32_t, struct ssh *); +int input_gssapi_errtok(int, u_int32_t, struct ssh *); #endif void userauth(Authctxt *, char *); @@ -319,7 +319,7 @@ static int sign_and_send_pubkey(Authctxt *, Identity *); static void pubkey_prepare(Authctxt *); static void pubkey_cleanup(Authctxt *); static void pubkey_reset(Authctxt *); -static Key *load_identity_file(Identity *); +static struct sshkey *load_identity_file(Identity *); static Authmethod *authmethod_get(char *authlist); static Authmethod *authmethod_lookup(const char *name); @@ -397,10 +397,12 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); + ssh->authctxt = &authctxt; ssh_dispatch_init(ssh, &input_userauth_error); ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info); ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept); - ssh_dispatch_run(ssh, DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */ + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */ + ssh->authctxt = NULL; pubkey_cleanup(&authctxt); ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); @@ -412,10 +414,9 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, /* ARGSUSED */ int -input_userauth_service_accept(int type, u_int32_t seqnr, void *ctxt) +input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; - struct ssh *ssh = active_state; + Authctxt *authctxt = ssh->authctxt; int r; if (ssh_packet_remaining(ssh) > 0) { @@ -446,9 +447,9 @@ input_userauth_service_accept(int type, u_int32_t seqnr, void *ctxt) /* ARGSUSED */ int -input_userauth_ext_info(int type, u_int32_t seqnr, void *ctxt) +input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh) { - return kex_input_ext_info(type, seqnr, active_state); + return kex_input_ext_info(type, seqnr, ssh); } void @@ -468,7 +469,8 @@ userauth(Authctxt *authctxt, char *authlist) for (;;) { Authmethod *method = authmethod_get(authlist); if (method == NULL) - fatal("Permission denied (%s).", authlist); + fatal("%s@%s: Permission denied (%s).", + authctxt->server_user, authctxt->host, authlist); authctxt->method = method; /* reset the per method handler */ @@ -488,7 +490,7 @@ userauth(Authctxt *authctxt, char *authlist) /* ARGSUSED */ int -input_userauth_error(int type, u_int32_t seq, void *ctxt) +input_userauth_error(int type, u_int32_t seq, struct ssh *ssh) { fatal("input_userauth_error: bad message during authentication: " "type %d", type); @@ -497,7 +499,7 @@ input_userauth_error(int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -input_userauth_banner(int type, u_int32_t seq, void *ctxt) +input_userauth_banner(int type, u_int32_t seq, struct ssh *ssh) { char *msg, *lang; u_int len; @@ -514,9 +516,9 @@ input_userauth_banner(int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -input_userauth_success(int type, u_int32_t seq, void *ctxt) +input_userauth_success(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; if (authctxt == NULL) fatal("input_userauth_success: no authentication context"); @@ -531,9 +533,9 @@ input_userauth_success(int type, u_int32_t seq, void *ctxt) } int -input_userauth_success_unexpected(int type, u_int32_t seq, void *ctxt) +input_userauth_success_unexpected(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; if (authctxt == NULL) fatal("%s: no authentication context", __func__); @@ -545,9 +547,9 @@ input_userauth_success_unexpected(int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -input_userauth_failure(int type, u_int32_t seq, void *ctxt) +input_userauth_failure(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; char *authlist = NULL; int partial; @@ -571,10 +573,10 @@ input_userauth_failure(int type, u_int32_t seq, void *ctxt) /* ARGSUSED */ int -input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) +input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; - Key *key = NULL; + Authctxt *authctxt = ssh->authctxt; + struct sshkey *key = NULL; Identity *id = NULL; Buffer b; int pktype, sent = 0; @@ -702,9 +704,9 @@ userauth_gssapi(Authctxt *authctxt) } static OM_uint32 -process_gssapi_token(void *ctxt, gss_buffer_t recv_tok) +process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt = authctxt->methoddata; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; @@ -757,9 +759,9 @@ process_gssapi_token(void *ctxt, gss_buffer_t recv_tok) /* ARGSUSED */ int -input_gssapi_response(int type, u_int32_t plen, void *ctxt) +input_gssapi_response(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; int oidlen; char *oidv; @@ -787,7 +789,7 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) free(oidv); - if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) { + if (GSS_ERROR(process_gssapi_token(ssh, GSS_C_NO_BUFFER))) { /* Start again with next method on list */ debug("Trying to start again"); userauth(authctxt, NULL); @@ -798,9 +800,9 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) /* ARGSUSED */ int -input_gssapi_token(int type, u_int32_t plen, void *ctxt) +input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; gss_buffer_desc recv_tok; OM_uint32 status; u_int slen; @@ -813,7 +815,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) packet_check_eom(); - status = process_gssapi_token(ctxt, &recv_tok); + status = process_gssapi_token(ssh, &recv_tok); free(recv_tok.value); @@ -827,9 +829,9 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) /* ARGSUSED */ int -input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) +input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; @@ -858,7 +860,7 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) /* ARGSUSED */ int -input_gssapi_error(int type, u_int32_t plen, void *ctxt) +input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) { char *msg; char *lang; @@ -893,7 +895,7 @@ int userauth_passwd(Authctxt *authctxt) { static int attempt = 0; - char prompt[150]; + char prompt[256]; char *password; const char *host = options.host_key_alias ? options.host_key_alias : authctxt->host; @@ -929,11 +931,11 @@ userauth_passwd(Authctxt *authctxt) */ /* ARGSUSED */ int -input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) +input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; char *info, *lang, *password = NULL, *retype = NULL; - char prompt[150]; + char prompt[256]; const char *host; debug2("input_userauth_passwd_changereq"); @@ -1015,7 +1017,7 @@ static int identity_sign(struct identity *id, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat) { - Key *prv; + struct sshkey *prv; int ret; /* the agent supports this key */ @@ -1035,6 +1037,11 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp, /* load the private key from the file */ if ((prv = load_identity_file(id)) == NULL) return SSH_ERR_KEY_NOT_FOUND; + if (id->key != NULL && !sshkey_equal_public(prv, id->key)) { + error("%s: private key %s contents do not match public", + __func__, id->filename); + return SSH_ERR_KEY_NOT_FOUND; + } ret = sshkey_sign(prv, sigp, lenp, data, datalen, key_sign_encode(prv), compat); sshkey_free(prv); @@ -1225,10 +1232,10 @@ send_pubkey_test(Authctxt *authctxt, Identity *id) return 1; } -static Key * +static struct sshkey * load_identity_file(Identity *id) { - Key *private = NULL; + struct sshkey *private = NULL; char prompt[300], *passphrase, *comment; int r, perm_ok = 0, quit = 0, i; struct stat st; @@ -1317,8 +1324,6 @@ pubkey_prepare(Authctxt *authctxt) /* list of keys stored in the filesystem and PKCS#11 */ for (i = 0; i < options.num_identity_files; i++) { key = options.identity_keys[i]; - if (key && key->type == KEY_RSA1) - continue; if (key && key->cert && key->cert->type != SSH2_CERT_TYPE_USER) continue; options.identity_keys[i] = NULL; @@ -1347,7 +1352,7 @@ pubkey_prepare(Authctxt *authctxt) if (r != SSH_ERR_AGENT_NOT_PRESENT) debug("%s: ssh_get_authentication_socket: %s", __func__, ssh_err(r)); - } else if ((r = ssh_fetch_identitylist(agent_fd, 2, &idlist)) != 0) { + } else if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) { if (r != SSH_ERR_AGENT_NO_IDENTITIES) debug("%s: ssh_fetch_identitylist: %s", __func__, ssh_err(r)); @@ -1471,7 +1476,7 @@ try_identity(Identity *id) key_type(id->key), id->filename); return (0); } - return (id->key->type != KEY_RSA1); + return 1; } int @@ -1479,6 +1484,7 @@ userauth_pubkey(Authctxt *authctxt) { Identity *id; int sent = 0; + char *fp; while ((id = TAILQ_FIRST(&authctxt->keys))) { if (id->tried++) @@ -1493,8 +1499,16 @@ userauth_pubkey(Authctxt *authctxt) */ if (id->key != NULL) { if (try_identity(id)) { - debug("Offering %s public key: %s", - key_type(id->key), id->filename); + if ((fp = sshkey_fingerprint(id->key, + options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) { + error("%s: sshkey_fingerprint failed", + __func__); + return 0; + } + debug("Offering public key: %s %s %s", + sshkey_type(id->key), fp, id->filename); + free(fp); sent = send_pubkey_test(authctxt, id); } } else { @@ -1552,9 +1566,9 @@ userauth_kbdint(Authctxt *authctxt) * parse INFO_REQUEST, prompt user and send INFO_RESPONSE */ int -input_userauth_info_req(int type, u_int32_t seq, void *ctxt) +input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh) { - Authctxt *authctxt = ctxt; + Authctxt *authctxt = ssh->authctxt; char *name, *inst, *lang, *prompt, *response; u_int num_prompts, i; int echo = 0; @@ -1755,7 +1769,6 @@ userauth_hostbased(Authctxt *authctxt) private = NULL; for (i = 0; i < authctxt->sensitive->nkeys; i++) { if (authctxt->sensitive->keys[i] == NULL || - authctxt->sensitive->keys[i]->type == KEY_RSA1 || authctxt->sensitive->keys[i]->type == KEY_UNSPEC) continue; if (match_pattern_list( diff --git a/sshd.0 b/sshd.0 index 6cd5f038c3c9..92c8ec53306c 100644 --- a/sshd.0 +++ b/sshd.0 @@ -134,7 +134,7 @@ AUTHENTICATION client selects the encryption algorithm to use from those offered by the server. Additionally, session integrity is provided through a cryptographic message authentication code (hmac-md5, hmac-sha1, umac-64, - umac-128, hmac-ripemd160, hmac-sha2-256 or hmac-sha2-512). + umac-128, hmac-sha2-256 or hmac-sha2-512). Finally, the server and the client enter an authentication dialog. The client tries to authenticate itself using host-based authentication, @@ -412,13 +412,19 @@ SSH_KNOWN_HOSTS FILE FORMAT should be used on a key line. Hostnames is a comma-separated list of patterns (M-bM-^@M-^X*M-bM-^@M-^Y and M-bM-^@M-^X?M-bM-^@M-^Y act as - wildcards); each pattern in turn is matched against the canonical host - name (when authenticating a client) or against the user-supplied name - (when authenticating a server). A pattern may also be preceded by M-bM-^@M-^X!M-bM-^@M-^Y to - indicate negation: if the host name matches a negated pattern, it is not - accepted (by that line) even if it matched another pattern on the line. - A hostname or address may optionally be enclosed within M-bM-^@M-^X[M-bM-^@M-^Y and M-bM-^@M-^X]M-bM-^@M-^Y - brackets then followed by M-bM-^@M-^X:M-bM-^@M-^Y and a non-standard port number. + wildcards); each pattern in turn is matched against the host name. When + sshd is authenticating a client, such as when using + HostbasedAuthentication, this will be the canonical client host name. + When ssh(1) is authenticating a server, this will be the host name given + by the user, the value of the ssh(1) HostkeyAlias if it was specified, or + the canonical server hostname if the ssh(1) CanonicalizeHostname option + was used. + + A pattern may also be preceded by M-bM-^@M-^X!M-bM-^@M-^Y to indicate negation: if the host + name matches a negated pattern, it is not accepted (by that line) even if + it matched another pattern on the line. A hostname or address may + optionally be enclosed within M-bM-^@M-^X[M-bM-^@M-^Y and M-bM-^@M-^X]M-bM-^@M-^Y brackets then followed by M-bM-^@M-^X:M-bM-^@M-^Y + and a non-standard port number. Alternately, hostnames may be stored in a hashed form which hides host names and addresses should the file's contents be disclosed. Hashed @@ -623,4 +629,4 @@ AUTHORS versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support for privilege separation. -OpenBSD 6.0 January 30, 2017 OpenBSD 6.0 +OpenBSD 6.2 June 24, 2017 OpenBSD 6.2 diff --git a/sshd.8 b/sshd.8 index 7725a692c060..a4201146bc23 100644 --- a/sshd.8 +++ b/sshd.8 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd.8,v 1.288 2017/01/30 23:27:39 dtucker Exp $ -.Dd $Mdocdate: January 30 2017 $ +.\" $OpenBSD: sshd.8,v 1.291 2017/06/24 06:28:50 jmc Exp $ +.Dd $Mdocdate: June 24 2017 $ .Dt SSHD 8 .Os .Sh NAME @@ -260,7 +260,7 @@ The client selects the encryption algorithm to use from those offered by the server. Additionally, session integrity is provided through a cryptographic message authentication code -(hmac-md5, hmac-sha1, umac-64, umac-128, hmac-ripemd160, +(hmac-md5, hmac-sha1, umac-64, umac-128, hmac-sha2-256 or hmac-sha2-512). .Pp Finally, the server and the client enter an authentication dialog. @@ -652,9 +652,23 @@ Hostnames is a comma-separated list of patterns and .Ql \&? act as -wildcards); each pattern in turn is matched against the canonical host -name (when authenticating a client) or against the user-supplied -name (when authenticating a server). +wildcards); each pattern in turn is matched against the host name. +When +.Nm sshd +is authenticating a client, such as when using +.Cm HostbasedAuthentication , +this will be the canonical client host name. +When +.Xr ssh 1 +is authenticating a server, this will be the host name +given by the user, the value of the +.Xr ssh 1 +.Cm HostkeyAlias +if it was specified, or the canonical server hostname if the +.Xr ssh 1 +.Cm CanonicalizeHostname +option was used. +.Pp A pattern may also be preceded by .Ql \&! to indicate negation: if the host name matches a negated diff --git a/sshd.c b/sshd.c index 010a2c38ab95..51a1aaf6ec86 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.485 2017/03/15 03:52:30 deraadt Exp $ */ +/* $OpenBSD: sshd.c,v 1.492 2017/09/12 06:32:07 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -88,7 +88,6 @@ #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" -#include "rsa.h" #include "sshpty.h" #include "packet.h" #include "log.h" @@ -195,10 +194,10 @@ int have_agent = 0; * not very useful. Currently, memory locking is not implemented. */ struct { - Key **host_keys; /* all private host keys */ - Key **host_pubkeys; /* all public host keys */ - Key **host_certificates; /* all public host certificates */ - int have_ssh2_key; + struct sshkey **host_keys; /* all private host keys */ + struct sshkey **host_pubkeys; /* all public host keys */ + struct sshkey **host_certificates; /* all public host certificates */ + int have_ssh2_key; } sensitive_data; /* This is set to true when a signal is received. */ @@ -223,6 +222,7 @@ int startup_pipe; /* in child */ int use_privsep = -1; struct monitor *pmonitor = NULL; int privsep_is_preauth = 1; +static int privsep_chroot = 1; /* global authentication context */ Authctxt *the_authctxt = NULL; @@ -449,10 +449,8 @@ sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) chop(server_version_string); debug("Local version string %.200s", server_version_string); - if (remote_major == 2 || - (remote_major == 1 && remote_minor == 99)) { - enable_compat20(); - } else { + if (remote_major != 2 || + (remote_major == 1 && remote_minor != 99)) { s = "Protocol major versions differ.\n"; (void) atomicio(vwrite, sock_out, s, strlen(s)); close(sock_in); @@ -487,7 +485,7 @@ destroy_sensitive_data(void) void demote_sensitive_data(void) { - Key *tmp; + struct sshkey *tmp; int i; for (i = 0; i < options.num_host_key_files; i++) { @@ -541,7 +539,7 @@ privsep_preauth_child(void) demote_sensitive_data(); /* Demote the child */ - if (getuid() == 0 || geteuid() == 0) { + if (privsep_chroot) { /* Change our root directory */ if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, @@ -650,6 +648,7 @@ privsep_postauth(Authctxt *authctxt) else if (pmonitor->m_pid != 0) { verbose("User child is on pid %ld", (long)pmonitor->m_pid); buffer_clear(&loginmsg); + monitor_clear_keystate(pmonitor); monitor_child_postauth(pmonitor); /* NEVERREACHED */ @@ -687,7 +686,7 @@ list_hostkey_types(void) const char *p; char *ret; int i; - Key *key; + struct sshkey *key; buffer_init(&b); for (i = 0; i < options.num_host_key_files; i++) { @@ -743,11 +742,11 @@ list_hostkey_types(void) return ret; } -static Key * +static struct sshkey * get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) { int i; - Key *key; + struct sshkey *key; for (i = 0; i < options.num_host_key_files; i++) { switch (type) { @@ -771,19 +770,19 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) return NULL; } -Key * +struct sshkey * get_hostkey_public_by_type(int type, int nid, struct ssh *ssh) { return get_hostkey_by_type(type, nid, 0, ssh); } -Key * +struct sshkey * get_hostkey_private_by_type(int type, int nid, struct ssh *ssh) { return get_hostkey_by_type(type, nid, 1, ssh); } -Key * +struct sshkey * get_hostkey_by_index(int ind) { if (ind < 0 || ind >= options.num_host_key_files) @@ -791,7 +790,7 @@ get_hostkey_by_index(int ind) return (sensitive_data.host_keys[ind]); } -Key * +struct sshkey * get_hostkey_public_by_index(int ind, struct ssh *ssh) { if (ind < 0 || ind >= options.num_host_key_files) @@ -800,7 +799,7 @@ get_hostkey_public_by_index(int ind, struct ssh *ssh) } int -get_hostkey_index(Key *key, int compare, struct ssh *ssh) +get_hostkey_index(struct sshkey *key, int compare, struct ssh *ssh) { int i; @@ -1367,8 +1366,8 @@ main(int ac, char **av) u_int n; u_int64_t ibytes, obytes; mode_t new_umask; - Key *key; - Key *pubkey; + struct sshkey *key; + struct sshkey *pubkey; int keytype; Authctxt *authctxt; struct connection_info *connection_info = get_connection_info(0, 0); @@ -1622,9 +1621,6 @@ main(int ac, char **av) "enabled authentication methods"); } - /* set default channel AF */ - channel_set_af(options.address_family); - /* Check that there are no remaining arguments. */ if (optind < ac) { fprintf(stderr, "Extra argument %s.\n", av[optind]); @@ -1640,8 +1636,9 @@ main(int ac, char **av) ); /* Store privilege separation user for later use if required. */ + privsep_chroot = use_privsep && (getuid() == 0 || geteuid() == 0); if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { - if (use_privsep || options.kerberos_authentication) + if (privsep_chroot || options.kerberos_authentication) fatal("Privilege separation user %s does not exist", SSH_PRIVSEP_USER); } else { @@ -1655,9 +1652,9 @@ main(int ac, char **av) /* load host keys */ sensitive_data.host_keys = xcalloc(options.num_host_key_files, - sizeof(Key *)); + sizeof(struct sshkey *)); sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files, - sizeof(Key *)); + sizeof(struct sshkey *)); if (options.host_key_agent) { if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) @@ -1676,14 +1673,6 @@ main(int ac, char **av) key = key_load_private(options.host_key_files[i], "", NULL); pubkey = key_load_public(options.host_key_files[i], NULL); - if ((pubkey != NULL && pubkey->type == KEY_RSA1) || - (key != NULL && key->type == KEY_RSA1)) { - verbose("Ignoring RSA1 key %s", - options.host_key_files[i]); - key_free(key); - key_free(pubkey); - continue; - } if (pubkey == NULL && key != NULL) pubkey = key_demote(key); sensitive_data.host_keys[i] = key; @@ -1729,7 +1718,7 @@ main(int ac, char **av) * indices to the public keys that they relate to. */ sensitive_data.host_certificates = xcalloc(options.num_host_key_files, - sizeof(Key *)); + sizeof(struct sshkey *)); for (i = 0; i < options.num_host_key_files; i++) sensitive_data.host_certificates[i] = NULL; @@ -1767,7 +1756,7 @@ main(int ac, char **av) key_type(key)); } - if (use_privsep) { + if (privsep_chroot) { struct stat st; if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) || @@ -1963,8 +1952,14 @@ main(int ac, char **av) packet_set_connection(sock_in, sock_out); packet_set_server(); ssh = active_state; /* XXX */ + check_ip_options(ssh); + /* Prepare the channels layer */ + channel_init_channels(ssh); + channel_set_af(ssh, options.address_family); + process_permitopen(ssh, &options); + /* Set SO_KEEPALIVE if requested. */ if (options.tcp_keep_alive && packet_connection_is_on_socket() && setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) @@ -2040,6 +2035,7 @@ main(int ac, char **av) */ if (use_privsep) { mm_send_keystate(pmonitor); + packet_clear_keys(); exit(0); } @@ -2087,10 +2083,10 @@ main(int ac, char **av) options.client_alive_count_max); /* Try to send all our hostkeys to the client */ - notify_hostkeys(active_state); + notify_hostkeys(ssh); /* Start session. */ - do_authenticated(authctxt); + do_authenticated(ssh, authctxt); /* The connection has been terminated. */ packet_get_bytes(&ibytes, &obytes); @@ -2117,8 +2113,9 @@ main(int ac, char **av) } int -sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, size_t *slen, - const u_char *data, size_t dlen, const char *alg, u_int flag) +sshd_hostkey_sign(struct sshkey *privkey, struct sshkey *pubkey, + u_char **signature, size_t *slen, const u_char *data, size_t dlen, + const char *alg, u_int flag) { int r; u_int xxx_slen, xxx_dlen = dlen; @@ -2198,7 +2195,7 @@ do_ssh2_kex(void) kex->host_key_index=&get_hostkey_index; kex->sign = sshd_hostkey_sign; - dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); + ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); session_id2 = kex->session_id; session_id2_len = kex->session_id_len; @@ -2217,8 +2214,10 @@ do_ssh2_kex(void) void cleanup_exit(int i) { + struct ssh *ssh = active_state; /* XXX */ + if (the_authctxt) { - do_cleanup(the_authctxt); + do_cleanup(ssh, the_authctxt); if (use_privsep && privsep_is_preauth && pmonitor != NULL && pmonitor->m_pid > 1) { debug("Killing privsep child %d", pmonitor->m_pid); diff --git a/sshd_config.0 b/sshd_config.0 index b0160aa87fb9..678ee14b4d3d 100644 --- a/sshd_config.0 +++ b/sshd_config.0 @@ -3,9 +3,6 @@ SSHD_CONFIG(5) File Formats Manual SSHD_CONFIG(5) NAME sshd_config M-bM-^@M-^S OpenSSH SSH daemon configuration file -SYNOPSIS - /etc/ssh/sshd_config - DESCRIPTION sshd(8) reads configuration data from /etc/ssh/sshd_config (or the file specified with -f on the command line). The file contains keyword- @@ -120,6 +117,11 @@ DESCRIPTION Note that each authentication method listed should also be explicitly enabled in the configuration. + The available authentication methods are: "gssapi-with-mic", + "hostbased", "keyboard-interactive", "none" (used for access to + password-less accounts when PermitEmptyPassword is enabled), + "password" and "publickey". + AuthorizedKeysCommand Specifies a program to be used to look up the user's public keys. The program must be owned by root, not writable by group or @@ -253,11 +255,6 @@ DESCRIPTION aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com - arcfour - arcfour128 - arcfour256 - blowfish-cbc - cast128-cbc chacha20-poly1305@openssh.com The default is: @@ -329,6 +326,13 @@ DESCRIPTION TCP and StreamLocal. This option overrides all other forwarding- related options and may simplify restricted configurations. + ExposeAuthInfo + Writes a temporary file containing a list of authentication + methods and public credentials (e.g. keys) used to authenticate + the user. The location of the file is exposed to the user + session through the SSH_USER_AUTH environment variable. The + default is no. + FingerprintHash Specifies the hash algorithm used when logging key fingerprints. Valid options are: md5 and sha256. The default is sha256. @@ -467,14 +471,14 @@ DESCRIPTION IPQoS Specifies the IPv4 type-of-service or DSCP class for the connection. Accepted values are af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3, - cs4, cs5, cs6, cs7, ef, lowdelay, throughput, reliability, or a - numeric value. This option may take one or two arguments, - separated by whitespace. If one argument is specified, it is - used as the packet class unconditionally. If two values are - specified, the first is automatically selected for interactive - sessions and the second for non-interactive sessions. The - default is lowdelay for interactive sessions and throughput for - non-interactive sessions. + cs4, cs5, cs6, cs7, ef, lowdelay, throughput, reliability, a + numeric value, or none to use the operating system default. This + option may take one or two arguments, separated by whitespace. + If one argument is specified, it is used as the packet class + unconditionally. If two values are specified, the first is + automatically selected for interactive sessions and the second + for non-interactive sessions. The default is lowdelay for + interactive sessions and throughput for non-interactive sessions. KbdInteractiveAuthentication Specifies whether to allow keyboard-interactive authentication. @@ -573,7 +577,6 @@ DESCRIPTION hmac-md5 hmac-md5-96 - hmac-ripemd160 hmac-sha1 hmac-sha1-96 hmac-sha2-256 @@ -582,7 +585,6 @@ DESCRIPTION umac-128@openssh.com hmac-md5-etm@openssh.com hmac-md5-96-etm@openssh.com - hmac-ripemd160-etm@openssh.com hmac-sha1-etm@openssh.com hmac-sha1-96-etm@openssh.com hmac-sha2-256-etm@openssh.com @@ -634,7 +636,7 @@ DESCRIPTION ClientAliveInterval, DenyGroups, DenyUsers, ForceCommand, GatewayPorts, GSSAPIAuthentication, HostbasedAcceptedKeyTypes, HostbasedAuthentication, HostbasedUsesNameFromPacketOnly, IPQoS, - KbdInteractiveAuthentication, KerberosAuthentication, + KbdInteractiveAuthentication, KerberosAuthentication, LogLevel, MaxAuthTries, MaxSessions, PasswordAuthentication, PermitEmptyPasswords, PermitOpen, PermitRootLogin, PermitTTY, PermitTunnel, PermitUserRC, PubkeyAcceptedKeyTypes, @@ -1017,4 +1019,4 @@ AUTHORS versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support for privilege separation. -OpenBSD 6.0 March 14, 2017 OpenBSD 6.0 +OpenBSD 6.2 September 27, 2017 OpenBSD 6.2 diff --git a/sshd_config.5 b/sshd_config.5 index ac6ccc793fbe..251b7467fd28 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -33,15 +33,13 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.243 2017/03/14 07:19:07 djm Exp $ -.Dd $Mdocdate: March 14 2017 $ +.\" $OpenBSD: sshd_config.5,v 1.253 2017/09/27 06:45:53 jmc Exp $ +.Dd $Mdocdate: September 27 2017 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME .Nm sshd_config .Nd OpenSSH SSH daemon configuration file -.Sh SYNOPSIS -.Nm /etc/ssh/sshd_config .Sh DESCRIPTION .Xr sshd 8 reads configuration data from @@ -225,6 +223,18 @@ requires successful authentication using two different public keys. .Pp Note that each authentication method listed should also be explicitly enabled in the configuration. +.Pp +The available authentication methods are: +.Qq gssapi-with-mic , +.Qq hostbased , +.Qq keyboard-interactive , +.Qq none +(used for access to password-less accounts when +.Cm PermitEmptyPassword +is enabled), +.Qq password +and +.Qq publickey . .It Cm AuthorizedKeysCommand Specifies a program to be used to look up the user's public keys. The program must be owned by root, not writable by group or others and @@ -464,16 +474,6 @@ aes128-gcm@openssh.com .It aes256-gcm@openssh.com .It -arcfour -.It -arcfour128 -.It -arcfour256 -.It -blowfish-cbc -.It -cast128-cbc -.It chacha20-poly1305@openssh.com .El .Pp @@ -574,6 +574,14 @@ Disables all forwarding features, including X11, TCP and StreamLocal. This option overrides all other forwarding-related options and may simplify restricted configurations. +.It Cm ExposeAuthInfo +Writes a temporary file containing a list of authentication methods and +public credentials (e.g. keys) used to authenticate the user. +The location of the file is exposed to the user session through the +.Ev SSH_USER_AUTH +environment variable. +The default is +.Cm no . .It Cm FingerprintHash Specifies the hash algorithm used when logging key fingerprints. Valid options are: @@ -798,7 +806,9 @@ Accepted values are .Cm lowdelay , .Cm throughput , .Cm reliability , -or a numeric value. +a numeric value, or +.Cm none +to use the operating system default. This option may take one or two arguments, separated by whitespace. If one argument is specified, it is used as the packet class unconditionally. If two values are specified, the first is automatically selected for @@ -962,8 +972,6 @@ hmac-md5 .It hmac-md5-96 .It -hmac-ripemd160 -.It hmac-sha1 .It hmac-sha1-96 @@ -980,8 +988,6 @@ hmac-md5-etm@openssh.com .It hmac-md5-96-etm@openssh.com .It -hmac-ripemd160-etm@openssh.com -.It hmac-sha1-etm@openssh.com .It hmac-sha1-96-etm@openssh.com @@ -1080,6 +1086,7 @@ Available keywords are .Cm IPQoS , .Cm KbdInteractiveAuthentication , .Cm KerberosAuthentication , +.Cm LogLevel , .Cm MaxAuthTries , .Cm MaxSessions , .Cm PasswordAuthentication , diff --git a/ssherr.c b/ssherr.c index 68020706381c..3c0009d69d83 100644 --- a/ssherr.c +++ b/ssherr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssherr.c,v 1.5 2015/09/13 14:39:16 tim Exp $ */ +/* $OpenBSD: ssherr.c,v 1.7 2017/09/12 06:32:08 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -135,6 +135,10 @@ ssh_err(int n) return "Connection corrupted"; case SSH_ERR_PROTOCOL_ERROR: return "Protocol error"; + case SSH_ERR_KEY_LENGTH: + return "Invalid key length"; + case SSH_ERR_NUMBER_TOO_LARGE: + return "number is too large"; default: return "unknown error"; } diff --git a/ssherr.h b/ssherr.h index 6f771b4b78be..c0b59211e833 100644 --- a/ssherr.h +++ b/ssherr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssherr.h,v 1.3 2015/01/30 01:13:33 djm Exp $ */ +/* $OpenBSD: ssherr.h,v 1.5 2017/09/12 06:32:08 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -77,6 +77,8 @@ #define SSH_ERR_CONN_TIMEOUT -53 #define SSH_ERR_CONN_CORRUPT -54 #define SSH_ERR_PROTOCOL_ERROR -55 +#define SSH_ERR_KEY_LENGTH -56 +#define SSH_ERR_NUMBER_TOO_LARGE -57 /* Translate a numeric error code to a human-readable error string */ const char *ssh_err(int n); diff --git a/sshkey.c b/sshkey.c index 53a7674b5e74..e91c54f53bbd 100644 --- a/sshkey.c +++ b/sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.c,v 1.45 2017/03/10 04:07:20 djm Exp $ */ +/* $OpenBSD: sshkey.c,v 1.56 2017/08/12 06:42:52 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. @@ -51,7 +51,6 @@ #include "ssherr.h" #include "misc.h" #include "sshbuf.h" -#include "rsa.h" #include "cipher.h" #include "digest.h" #define SSHKEY_INTERNAL @@ -66,7 +65,7 @@ #define KDFNAME "bcrypt" #define AUTH_MAGIC "openssh-key-v1" #define SALT_LEN 16 -#define DEFAULT_CIPHERNAME "aes256-cbc" +#define DEFAULT_CIPHERNAME "aes256-ctr" #define DEFAULT_ROUNDS 16 /* Version identification string for SSH v1 identity files. */ @@ -89,9 +88,6 @@ static const struct keytype keytypes[] = { { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", KEY_ED25519_CERT, 0, 1, 0 }, #ifdef WITH_OPENSSL -# ifdef WITH_SSH1 - { NULL, "RSA1", KEY_RSA1, 0, 0, 0 }, -# endif { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 }, { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 }, { "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 }, @@ -238,10 +234,6 @@ sshkey_names_valid2(const char *names, int allow_wildcard) for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { type = sshkey_type_from_name(p); - if (type == KEY_RSA1) { - free(s); - return 0; - } if (type == KEY_UNSPEC) { if (allow_wildcard) { /* @@ -250,8 +242,6 @@ sshkey_names_valid2(const char *names, int allow_wildcard) * the component is accepted. */ for (kt = keytypes; kt->type != -1; kt++) { - if (kt->type == KEY_RSA1) - continue; if (match_pattern_list(kt->name, p, 0) != 0) break; @@ -272,7 +262,6 @@ sshkey_size(const struct sshkey *k) { switch (k->type) { #ifdef WITH_OPENSSL - case KEY_RSA1: case KEY_RSA: case KEY_RSA_CERT: return BN_num_bits(k->rsa->n); @@ -475,7 +464,6 @@ sshkey_new(int type) k->ed25519_pk = NULL; switch (k->type) { #ifdef WITH_OPENSSL - case KEY_RSA1: case KEY_RSA: case KEY_RSA_CERT: if ((rsa = RSA_new()) == NULL || @@ -533,7 +521,6 @@ sshkey_add_private(struct sshkey *k) { switch (k->type) { #ifdef WITH_OPENSSL - case KEY_RSA1: case KEY_RSA: case KEY_RSA_CERT: #define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL) @@ -589,7 +576,6 @@ sshkey_free(struct sshkey *k) return; switch (k->type) { #ifdef WITH_OPENSSL - case KEY_RSA1: case KEY_RSA: case KEY_RSA_CERT: if (k->rsa != NULL) @@ -667,7 +653,6 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) switch (a->type) { #ifdef WITH_OPENSSL - case KEY_RSA1: case KEY_RSA_CERT: case KEY_RSA: return a->rsa != NULL && b->rsa != NULL && @@ -884,25 +869,7 @@ sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg, r = SSH_ERR_INVALID_ARGUMENT; goto out; } - - if (k->type == KEY_RSA1) { -#ifdef WITH_OPENSSL - int nlen = BN_num_bytes(k->rsa->n); - int elen = BN_num_bytes(k->rsa->e); - - if (nlen < 0 || elen < 0 || nlen >= INT_MAX - elen) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - blob_len = nlen + elen; - if ((blob = malloc(blob_len)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - BN_bn2bin(k->rsa->n, blob); - BN_bn2bin(k->rsa->e, blob + nlen); -#endif /* WITH_OPENSSL */ - } else if ((r = to_blob(k, &blob, &blob_len, 1)) != 0) + if ((r = to_blob(k, &blob, &blob_len, 1)) != 0) goto out; if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) { r = SSH_ERR_ALLOC_FAIL; @@ -1194,39 +1161,6 @@ sshkey_fingerprint(const struct sshkey *k, int dgst_alg, return retval; } -#ifdef WITH_SSH1 -/* - * Reads a multiple-precision integer in decimal from the buffer, and advances - * the pointer. The integer must already be initialized. This function is - * permitted to modify the buffer. This leaves *cpp to point just beyond the - * last processed character. - */ -static int -read_decimal_bignum(char **cpp, BIGNUM *v) -{ - char *cp; - size_t e; - int skip = 1; /* skip white space */ - - cp = *cpp; - while (*cp == ' ' || *cp == '\t') - cp++; - e = strspn(cp, "0123456789"); - if (e == 0) - return SSH_ERR_INVALID_FORMAT; - if (e > SSHBUF_MAX_BIGNUM * 3) - return SSH_ERR_BIGNUM_TOO_LARGE; - if (cp[e] == '\0') - skip = 0; - else if (strchr(" \t\r\n", cp[e]) == NULL) - return SSH_ERR_INVALID_FORMAT; - cp[e] = '\0'; - if (BN_dec2bn(&v, cp) <= 0) - return SSH_ERR_INVALID_FORMAT; - *cpp = cp + e + skip; - return 0; -} -#endif /* WITH_SSH1 */ /* returns 0 ok, and < 0 error */ int @@ -1237,9 +1171,6 @@ sshkey_read(struct sshkey *ret, char **cpp) char *ep, *cp, *space; int r, type, curve_nid = -1; struct sshbuf *blob; -#ifdef WITH_SSH1 - u_long bits; -#endif /* WITH_SSH1 */ if (ret == NULL) return SSH_ERR_INVALID_ARGUMENT; @@ -1247,25 +1178,6 @@ sshkey_read(struct sshkey *ret, char **cpp) cp = *cpp; switch (ret->type) { - case KEY_RSA1: -#ifdef WITH_SSH1 - /* Get number of bits. */ - bits = strtoul(cp, &ep, 10); - if (*cp == '\0' || strchr(" \t\r\n", *ep) == NULL || - bits == 0 || bits > SSHBUF_MAX_BIGNUM * 8) - return SSH_ERR_INVALID_FORMAT; /* Bad bit count... */ - /* Get public exponent, public modulus. */ - if ((r = read_decimal_bignum(&ep, ret->rsa->e)) < 0) - return r; - if ((r = read_decimal_bignum(&ep, ret->rsa->n)) < 0) - return r; - /* validate the claimed number of bits */ - if (BN_num_bits(ret->rsa->n) != (int)bits) - return SSH_ERR_KEY_BITS_MISMATCH; - *cpp = ep; - retval = 0; -#endif /* WITH_SSH1 */ - break; case KEY_UNSPEC: case KEY_RSA: case KEY_DSA: @@ -1418,61 +1330,17 @@ sshkey_to_base64(const struct sshkey *key, char **b64p) return r; } -static int -sshkey_format_rsa1(const struct sshkey *key, struct sshbuf *b) -{ - int r = SSH_ERR_INTERNAL_ERROR; -#ifdef WITH_SSH1 - u_int bits = 0; - char *dec_e = NULL, *dec_n = NULL; - - if (key->rsa == NULL || key->rsa->e == NULL || - key->rsa->n == NULL) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - if ((dec_e = BN_bn2dec(key->rsa->e)) == NULL || - (dec_n = BN_bn2dec(key->rsa->n)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - /* size of modulus 'n' */ - if ((bits = BN_num_bits(key->rsa->n)) <= 0) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - if ((r = sshbuf_putf(b, "%u %s %s", bits, dec_e, dec_n)) != 0) - goto out; - - /* Success */ - r = 0; - out: - if (dec_e != NULL) - OPENSSL_free(dec_e); - if (dec_n != NULL) - OPENSSL_free(dec_n); -#endif /* WITH_SSH1 */ - - return r; -} - -static int +int sshkey_format_text(const struct sshkey *key, struct sshbuf *b) { int r = SSH_ERR_INTERNAL_ERROR; char *uu = NULL; - if (key->type == KEY_RSA1) { - if ((r = sshkey_format_rsa1(key, b)) != 0) - goto out; - } else { - /* Unsupported key types handled in sshkey_to_base64() */ - if ((r = sshkey_to_base64(key, &uu)) != 0) - goto out; - if ((r = sshbuf_putf(b, "%s %s", - sshkey_ssh_name(key), uu)) != 0) - goto out; - } + if ((r = sshkey_to_base64(key, &uu)) != 0) + goto out; + if ((r = sshbuf_putf(b, "%s %s", + sshkey_ssh_name(key), uu)) != 0) + goto out; r = 0; out: free(uu); @@ -1523,10 +1391,11 @@ rsa_generate_private_key(u_int bits, RSA **rsap) BIGNUM *f4 = NULL; int ret = SSH_ERR_INTERNAL_ERROR; - if (rsap == NULL || - bits < SSH_RSA_MINIMUM_MODULUS_SIZE || - bits > SSHBUF_MAX_BIGNUM * 8) + if (rsap == NULL) return SSH_ERR_INVALID_ARGUMENT; + if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE || + bits > SSHBUF_MAX_BIGNUM * 8) + return SSH_ERR_KEY_LENGTH; *rsap = NULL; if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; @@ -1554,8 +1423,10 @@ dsa_generate_private_key(u_int bits, DSA **dsap) DSA *private; int ret = SSH_ERR_INTERNAL_ERROR; - if (dsap == NULL || bits != 1024) + if (dsap == NULL) return SSH_ERR_INVALID_ARGUMENT; + if (bits != 1024) + return SSH_ERR_KEY_LENGTH; if ((private = DSA_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; @@ -1632,9 +1503,10 @@ ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap) EC_KEY *private; int ret = SSH_ERR_INTERNAL_ERROR; - if (nid == NULL || ecdsap == NULL || - (*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) + if (nid == NULL || ecdsap == NULL) return SSH_ERR_INVALID_ARGUMENT; + if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) + return SSH_ERR_KEY_LENGTH; *ecdsap = NULL; if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; @@ -1688,7 +1560,6 @@ sshkey_generate(int type, u_int bits, struct sshkey **keyp) break; # endif /* OPENSSL_HAS_ECC */ case KEY_RSA: - case KEY_RSA1: ret = rsa_generate_private_key(bits, &k->rsa); break; #endif /* WITH_OPENSSL */ @@ -1799,7 +1670,6 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) break; # endif /* OPENSSL_HAS_ECC */ case KEY_RSA: - case KEY_RSA1: case KEY_RSA_CERT: if ((n = sshkey_new(k->type)) == NULL) return SSH_ERR_ALLOC_FAIL; @@ -1893,8 +1763,9 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) goto out; } oprincipals = key->cert->principals; - key->cert->principals = reallocarray(key->cert->principals, - key->cert->nprincipals + 1, sizeof(*key->cert->principals)); + key->cert->principals = recallocarray(key->cert->principals, + key->cert->nprincipals, key->cert->nprincipals + 1, + sizeof(*key->cert->principals)); if (key->cert->principals == NULL) { free(principal); key->cert->principals = oprincipals; @@ -2009,6 +1880,10 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, ret = SSH_ERR_INVALID_FORMAT; goto out; } + if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { + ret = SSH_ERR_KEY_LENGTH; + goto out; + } #ifdef DEBUG_PK RSA_print_fp(stderr, key->rsa, 8); #endif @@ -2111,11 +1986,6 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, pk = NULL; break; case KEY_UNSPEC: - if ((key = sshkey_new(type)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - break; default: ret = SSH_ERR_KEY_TYPE_UNKNOWN; goto out; @@ -2269,7 +2139,6 @@ sshkey_demote(const struct sshkey *k, struct sshkey **dkp) if ((ret = sshkey_cert_copy(k, pk)) != 0) goto fail; /* FALLTHROUGH */ - case KEY_RSA1: case KEY_RSA: if ((pk->rsa = RSA_new()) == NULL || (pk->rsa->e = BN_dup(k->rsa->e)) == NULL || @@ -2378,7 +2247,8 @@ sshkey_drop_cert(struct sshkey *k) /* Sign a certified key, (re-)generating the signed certblob. */ int -sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) +sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, + sshkey_certify_signer *signer, void *signer_ctx) { struct sshbuf *principals = NULL; u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; @@ -2467,8 +2337,8 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) goto out; /* Sign the whole mess */ - if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), - sshbuf_len(cert), alg, 0)) != 0) + if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), + sshbuf_len(cert), alg, 0, signer_ctx)) != 0) goto out; /* Append signature and we are done */ @@ -2484,6 +2354,22 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) return ret; } +static int +default_key_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, + const char *alg, u_int compat, void *ctx) +{ + if (ctx != NULL) + return SSH_ERR_INVALID_ARGUMENT; + return sshkey_sign(key, sigp, lenp, data, datalen, alg, compat); +} + +int +sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) +{ + return sshkey_certify_custom(k, ca, alg, default_key_sign, NULL); +} + int sshkey_cert_check_authority(const struct sshkey *k, int want_host, int require_principal, @@ -2775,8 +2661,12 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || - (r = rsa_generate_additional_parameters(k->rsa)) != 0) + (r = ssh_rsa_generate_additional_parameters(k)) != 0) goto out; + if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { + r = SSH_ERR_KEY_LENGTH; + goto out; + } break; case KEY_RSA_CERT: if ((r = sshkey_froms(buf, &k)) != 0 || @@ -2785,8 +2675,12 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || - (r = rsa_generate_additional_parameters(k->rsa)) != 0) + (r = ssh_rsa_generate_additional_parameters(k)) != 0) goto out; + if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { + r = SSH_ERR_KEY_LENGTH; + goto out; + } break; #endif /* WITH_OPENSSL */ case KEY_ED25519: @@ -2828,7 +2722,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) switch (k->type) { case KEY_RSA: case KEY_RSA_CERT: - case KEY_RSA1: if (RSA_blinding_on(k->rsa, NULL) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; @@ -3057,12 +2950,8 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob, kdfname = "none"; } else if (ciphername == NULL) ciphername = DEFAULT_CIPHERNAME; - else if (cipher_number(ciphername) != SSH_CIPHER_SSH2) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } if ((cipher = cipher_by_name(ciphername)) == NULL) { - r = SSH_ERR_INTERNAL_ERROR; + r = SSH_ERR_INVALID_ARGUMENT; goto out; } @@ -3404,105 +3293,6 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, return r; } -#if WITH_SSH1 -/* - * Serialises the authentication (private) key to a blob, encrypting it with - * passphrase. The identification of the blob (lowest 64 bits of n) will - * precede the key to provide identification of the key without needing a - * passphrase. - */ -static int -sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob, - const char *passphrase, const char *comment) -{ - struct sshbuf *buffer = NULL, *encrypted = NULL; - u_char buf[8]; - int r, cipher_num; - struct sshcipher_ctx *ciphercontext = NULL; - const struct sshcipher *cipher; - u_char *cp; - - /* - * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting - * to another cipher; otherwise use SSH_AUTHFILE_CIPHER. - */ - cipher_num = (strcmp(passphrase, "") == 0) ? - SSH_CIPHER_NONE : SSH_CIPHER_3DES; - if ((cipher = cipher_by_number(cipher_num)) == NULL) - return SSH_ERR_INTERNAL_ERROR; - - /* This buffer is used to build the secret part of the private key. */ - if ((buffer = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - - /* Put checkbytes for checking passphrase validity. */ - if ((r = sshbuf_reserve(buffer, 4, &cp)) != 0) - goto out; - arc4random_buf(cp, 2); - memcpy(cp + 2, cp, 2); - - /* - * Store the private key (n and e will not be stored because they - * will be stored in plain text, and storing them also in encrypted - * format would just give known plaintext). - * Note: q and p are stored in reverse order to SSL. - */ - if ((r = sshbuf_put_bignum1(buffer, key->rsa->d)) != 0 || - (r = sshbuf_put_bignum1(buffer, key->rsa->iqmp)) != 0 || - (r = sshbuf_put_bignum1(buffer, key->rsa->q)) != 0 || - (r = sshbuf_put_bignum1(buffer, key->rsa->p)) != 0) - goto out; - - /* Pad the part to be encrypted to a size that is a multiple of 8. */ - explicit_bzero(buf, 8); - if ((r = sshbuf_put(buffer, buf, 8 - (sshbuf_len(buffer) % 8))) != 0) - goto out; - - /* This buffer will be used to contain the data in the file. */ - if ((encrypted = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - - /* First store keyfile id string. */ - if ((r = sshbuf_put(encrypted, LEGACY_BEGIN, - sizeof(LEGACY_BEGIN))) != 0) - goto out; - - /* Store cipher type and "reserved" field. */ - if ((r = sshbuf_put_u8(encrypted, cipher_num)) != 0 || - (r = sshbuf_put_u32(encrypted, 0)) != 0) - goto out; - - /* Store public key. This will be in plain text. */ - if ((r = sshbuf_put_u32(encrypted, BN_num_bits(key->rsa->n))) != 0 || - (r = sshbuf_put_bignum1(encrypted, key->rsa->n)) != 0 || - (r = sshbuf_put_bignum1(encrypted, key->rsa->e)) != 0 || - (r = sshbuf_put_cstring(encrypted, comment)) != 0) - goto out; - - /* Allocate space for the private part of the key in the buffer. */ - if ((r = sshbuf_reserve(encrypted, sshbuf_len(buffer), &cp)) != 0) - goto out; - - if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase, - CIPHER_ENCRYPT)) != 0) - goto out; - if ((r = cipher_crypt(ciphercontext, 0, cp, - sshbuf_ptr(buffer), sshbuf_len(buffer), 0, 0)) != 0) - goto out; - - r = sshbuf_putb(blob, encrypted); - - out: - cipher_free(ciphercontext); - explicit_bzero(buf, sizeof(buf)); - sshbuf_free(buffer); - sshbuf_free(encrypted); - - return r; -} -#endif /* WITH_SSH1 */ #ifdef WITH_OPENSSL /* convert SSH v2 key in OpenSSL PEM format */ @@ -3513,11 +3303,7 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob, int success, r; int blen, len = strlen(_passphrase); u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; -#if (OPENSSL_VERSION_NUMBER < 0x00907000L) - const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL; -#else - const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; -#endif + const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; const u_char *bptr; BIO *bio = NULL; @@ -3569,11 +3355,6 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, int force_new_format, const char *new_format_cipher, int new_format_rounds) { switch (key->type) { -#ifdef WITH_SSH1 - case KEY_RSA1: - return sshkey_private_rsa1_to_blob(key, blob, - passphrase, comment); -#endif /* WITH_SSH1 */ #ifdef WITH_OPENSSL case KEY_DSA: case KEY_ECDSA: @@ -3593,184 +3374,66 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, } } -#ifdef WITH_SSH1 -/* - * Parse the public, unencrypted portion of a RSA1 key. - */ -int -sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob, - struct sshkey **keyp, char **commentp) -{ - int r; - struct sshkey *pub = NULL; - struct sshbuf *copy = NULL; - - if (keyp != NULL) - *keyp = NULL; - if (commentp != NULL) - *commentp = NULL; - - /* Check that it is at least big enough to contain the ID string. */ - if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN)) - return SSH_ERR_INVALID_FORMAT; - - /* - * Make sure it begins with the id string. Consume the id string - * from the buffer. - */ - if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0) - return SSH_ERR_INVALID_FORMAT; - /* Make a working copy of the keyblob and skip past the magic */ - if ((copy = sshbuf_fromb(blob)) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0) - goto out; - - /* Skip cipher type, reserved data and key bits. */ - if ((r = sshbuf_get_u8(copy, NULL)) != 0 || /* cipher type */ - (r = sshbuf_get_u32(copy, NULL)) != 0 || /* reserved */ - (r = sshbuf_get_u32(copy, NULL)) != 0) /* key bits */ - goto out; - - /* Read the public key from the buffer. */ - if ((pub = sshkey_new(KEY_RSA1)) == NULL || - (r = sshbuf_get_bignum1(copy, pub->rsa->n)) != 0 || - (r = sshbuf_get_bignum1(copy, pub->rsa->e)) != 0) - goto out; - - /* Finally, the comment */ - if ((r = sshbuf_get_string(copy, (u_char**)commentp, NULL)) != 0) - goto out; - - /* The encrypted private part is not parsed by this function. */ - - r = 0; - if (keyp != NULL) { - *keyp = pub; - pub = NULL; - } - out: - sshbuf_free(copy); - sshkey_free(pub); - return r; -} - -static int -sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase, - struct sshkey **keyp, char **commentp) -{ - int r; - u_int16_t check1, check2; - u_int8_t cipher_type; - struct sshbuf *decrypted = NULL, *copy = NULL; - u_char *cp; - char *comment = NULL; - struct sshcipher_ctx *ciphercontext = NULL; - const struct sshcipher *cipher; - struct sshkey *prv = NULL; - - if (keyp != NULL) - *keyp = NULL; - if (commentp != NULL) - *commentp = NULL; - - /* Check that it is at least big enough to contain the ID string. */ - if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN)) - return SSH_ERR_INVALID_FORMAT; - - /* - * Make sure it begins with the id string. Consume the id string - * from the buffer. - */ - if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0) - return SSH_ERR_INVALID_FORMAT; - - if ((prv = sshkey_new_private(KEY_RSA1)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((copy = sshbuf_fromb(blob)) == NULL || - (decrypted = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0) - goto out; - - /* Read cipher type. */ - if ((r = sshbuf_get_u8(copy, &cipher_type)) != 0 || - (r = sshbuf_get_u32(copy, NULL)) != 0) /* reserved */ - goto out; - - /* Read the public key and comment from the buffer. */ - if ((r = sshbuf_get_u32(copy, NULL)) != 0 || /* key bits */ - (r = sshbuf_get_bignum1(copy, prv->rsa->n)) != 0 || - (r = sshbuf_get_bignum1(copy, prv->rsa->e)) != 0 || - (r = sshbuf_get_cstring(copy, &comment, NULL)) != 0) - goto out; - - /* Check that it is a supported cipher. */ - cipher = cipher_by_number(cipher_type); - if (cipher == NULL) { - r = SSH_ERR_KEY_UNKNOWN_CIPHER; - goto out; - } - /* Initialize space for decrypted data. */ - if ((r = sshbuf_reserve(decrypted, sshbuf_len(copy), &cp)) != 0) - goto out; - - /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ - if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase, - CIPHER_DECRYPT)) != 0) - goto out; - if ((r = cipher_crypt(ciphercontext, 0, cp, - sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0) - goto out; - - if ((r = sshbuf_get_u16(decrypted, &check1)) != 0 || - (r = sshbuf_get_u16(decrypted, &check2)) != 0) - goto out; - if (check1 != check2) { - r = SSH_ERR_KEY_WRONG_PASSPHRASE; - goto out; - } - - /* Read the rest of the private key. */ - if ((r = sshbuf_get_bignum1(decrypted, prv->rsa->d)) != 0 || - (r = sshbuf_get_bignum1(decrypted, prv->rsa->iqmp)) != 0 || - (r = sshbuf_get_bignum1(decrypted, prv->rsa->q)) != 0 || - (r = sshbuf_get_bignum1(decrypted, prv->rsa->p)) != 0) - goto out; - - /* calculate p-1 and q-1 */ - if ((r = rsa_generate_additional_parameters(prv->rsa)) != 0) - goto out; - - /* enable blinding */ - if (RSA_blinding_on(prv->rsa, NULL) != 1) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - r = 0; - if (keyp != NULL) { - *keyp = prv; - prv = NULL; - } - if (commentp != NULL) { - *commentp = comment; - comment = NULL; - } - out: - cipher_free(ciphercontext); - free(comment); - sshkey_free(prv); - sshbuf_free(copy); - sshbuf_free(decrypted); - return r; -} -#endif /* WITH_SSH1 */ #ifdef WITH_OPENSSL +static int +translate_libcrypto_error(unsigned long pem_err) +{ + int pem_reason = ERR_GET_REASON(pem_err); + + switch (ERR_GET_LIB(pem_err)) { + case ERR_LIB_PEM: + switch (pem_reason) { + case PEM_R_BAD_PASSWORD_READ: + case PEM_R_PROBLEMS_GETTING_PASSWORD: + case PEM_R_BAD_DECRYPT: + return SSH_ERR_KEY_WRONG_PASSPHRASE; + default: + return SSH_ERR_INVALID_FORMAT; + } + case ERR_LIB_EVP: + switch (pem_reason) { + case EVP_R_BAD_DECRYPT: + return SSH_ERR_KEY_WRONG_PASSPHRASE; + case EVP_R_BN_DECODE_ERROR: + case EVP_R_DECODE_ERROR: +#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR + case EVP_R_PRIVATE_KEY_DECODE_ERROR: +#endif + return SSH_ERR_INVALID_FORMAT; + default: + return SSH_ERR_LIBCRYPTO_ERROR; + } + case ERR_LIB_ASN1: + return SSH_ERR_INVALID_FORMAT; + } + return SSH_ERR_LIBCRYPTO_ERROR; +} + +static void +clear_libcrypto_errors(void) +{ + while (ERR_get_error() != 0) + ; +} + +/* + * Translate OpenSSL error codes to determine whether + * passphrase is required/incorrect. + */ +static int +convert_libcrypto_error(void) +{ + /* + * Some password errors are reported at the beginning + * of the error queue. + */ + if (translate_libcrypto_error(ERR_peek_error()) == + SSH_ERR_KEY_WRONG_PASSPHRASE) + return SSH_ERR_KEY_WRONG_PASSPHRASE; + return translate_libcrypto_error(ERR_peek_last_error()); +} + static int sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, const char *passphrase, struct sshkey **keyp) @@ -3791,48 +3454,10 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, goto out; } + clear_libcrypto_errors(); if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, (char *)passphrase)) == NULL) { - unsigned long pem_err = ERR_peek_last_error(); - int pem_reason = ERR_GET_REASON(pem_err); - - /* - * Translate OpenSSL error codes to determine whether - * passphrase is required/incorrect. - */ - switch (ERR_GET_LIB(pem_err)) { - case ERR_LIB_PEM: - switch (pem_reason) { - case PEM_R_BAD_PASSWORD_READ: - case PEM_R_PROBLEMS_GETTING_PASSWORD: - case PEM_R_BAD_DECRYPT: - r = SSH_ERR_KEY_WRONG_PASSPHRASE; - goto out; - default: - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - case ERR_LIB_EVP: - switch (pem_reason) { - case EVP_R_BAD_DECRYPT: - r = SSH_ERR_KEY_WRONG_PASSPHRASE; - goto out; - case EVP_R_BN_DECODE_ERROR: - case EVP_R_DECODE_ERROR: -#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR - case EVP_R_PRIVATE_KEY_DECODE_ERROR: -#endif - r = SSH_ERR_INVALID_FORMAT; - goto out; - default: - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - case ERR_LIB_ASN1: - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - r = SSH_ERR_LIBCRYPTO_ERROR; + r = convert_libcrypto_error(); goto out; } if (pk->type == EVP_PKEY_RSA && @@ -3850,6 +3475,10 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } + if (BN_num_bits(prv->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { + r = SSH_ERR_KEY_LENGTH; + goto out; + } } else if (pk->type == EVP_PKEY_DSA && (type == KEY_UNSPEC || type == KEY_DSA)) { if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { @@ -3914,11 +3543,6 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, *commentp = NULL; switch (type) { -#ifdef WITH_SSH1 - case KEY_RSA1: - return sshkey_parse_private_rsa1(blob, passphrase, - keyp, commentp); -#endif /* WITH_SSH1 */ #ifdef WITH_OPENSSL case KEY_DSA: case KEY_ECDSA: @@ -3955,13 +3579,6 @@ sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase, if (commentp != NULL) *commentp = NULL; -#ifdef WITH_SSH1 - /* it's a SSH v1 key if the public key part is readable */ - if (sshkey_parse_public_rsa1_fileblob(buffer, NULL, NULL) == 0) { - return sshkey_parse_private_fileblob_type(buffer, KEY_RSA1, - passphrase, keyp, commentp); - } -#endif /* WITH_SSH1 */ return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC, passphrase, keyp, commentp); } diff --git a/sshkey.h b/sshkey.h index 1b9e42f45be0..9093eac517d9 100644 --- a/sshkey.h +++ b/sshkey.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.h,v 1.15 2017/03/10 04:07:20 djm Exp $ */ +/* $OpenBSD: sshkey.h,v 1.21 2017/07/01 13:50:45 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -46,14 +46,13 @@ # define EC_POINT void #endif /* WITH_OPENSSL */ -#define SSH_RSA_MINIMUM_MODULUS_SIZE 768 +#define SSH_RSA_MINIMUM_MODULUS_SIZE 1024 #define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20) struct sshbuf; /* Key types */ enum sshkey_types { - KEY_RSA1, KEY_RSA, KEY_DSA, KEY_ECDSA, @@ -125,6 +124,7 @@ int sshkey_fingerprint_raw(const struct sshkey *k, int, u_char **retp, size_t *lenp); const char *sshkey_type(const struct sshkey *); const char *sshkey_cert_type(const struct sshkey *); +int sshkey_format_text(const struct sshkey *, struct sshbuf *); int sshkey_write(const struct sshkey *, FILE *); int sshkey_read(struct sshkey *, char **); u_int sshkey_size(const struct sshkey *); @@ -137,13 +137,19 @@ int sshkey_type_is_cert(int); int sshkey_type_plain(int); int sshkey_to_certified(struct sshkey *); int sshkey_drop_cert(struct sshkey *); -int sshkey_certify(struct sshkey *, struct sshkey *, const char *); int sshkey_cert_copy(const struct sshkey *, struct sshkey *); int sshkey_cert_check_authority(const struct sshkey *, int, int, const char *, const char **); size_t sshkey_format_cert_validity(const struct sshkey_cert *, char *, size_t) __attribute__((__bounded__(__string__, 2, 3))); +int sshkey_certify(struct sshkey *, struct sshkey *, const char *); +/* Variant allowing use of a custom signature function (e.g. for ssh-agent) */ +typedef int sshkey_certify_signer(const struct sshkey *, u_char **, size_t *, + const u_char *, size_t, const char *, u_int, void *); +int sshkey_certify_custom(struct sshkey *, struct sshkey *, const char *, + sshkey_certify_signer *, void *); + int sshkey_ecdsa_nid_from_name(const char *); int sshkey_curve_name_to_nid(const char *); const char * sshkey_curve_nid_to_name(int); @@ -185,13 +191,14 @@ int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp); int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, const char *passphrase, const char *comment, int force_new_format, const char *new_format_cipher, int new_format_rounds); -int sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob, - struct sshkey **keyp, char **commentp); int sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase, struct sshkey **keyp, char **commentp); int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, const char *passphrase, struct sshkey **keyp, char **commentp); +/* XXX should be internal, but used by ssh-keygen */ +int ssh_rsa_generate_additional_parameters(struct sshkey *); + #ifdef SSHKEY_INTERNAL int ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, diff --git a/ttymodes.c b/ttymodes.c index db772c39c743..8451396353c9 100644 --- a/ttymodes.c +++ b/ttymodes.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ttymodes.c,v 1.30 2016/05/04 14:22:33 markus Exp $ */ +/* $OpenBSD: ttymodes.c,v 1.32 2017/04/30 23:26:54 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -59,12 +59,10 @@ #define TTY_OP_END 0 /* - * uint32 (u_int) follows speed in SSH1 and SSH2 + * uint32 (u_int) follows speed. */ -#define TTY_OP_ISPEED_PROTO1 192 -#define TTY_OP_OSPEED_PROTO1 193 -#define TTY_OP_ISPEED_PROTO2 128 -#define TTY_OP_OSPEED_PROTO2 129 +#define TTY_OP_ISPEED 128 +#define TTY_OP_OSPEED 129 /* * Converts POSIX speed_t to a baud rate. The values of the @@ -282,19 +280,8 @@ tty_make_modes(int fd, struct termios *tiop) struct termios tio; int baud; Buffer buf; - int tty_op_ospeed, tty_op_ispeed; - void (*put_arg)(Buffer *, u_int); buffer_init(&buf); - if (compat20) { - tty_op_ospeed = TTY_OP_OSPEED_PROTO2; - tty_op_ispeed = TTY_OP_ISPEED_PROTO2; - put_arg = buffer_put_int; - } else { - tty_op_ospeed = TTY_OP_OSPEED_PROTO1; - tty_op_ispeed = TTY_OP_ISPEED_PROTO1; - put_arg = (void (*)(Buffer *, u_int)) buffer_put_char; - } if (tiop == NULL) { if (fd == -1) { @@ -310,20 +297,20 @@ tty_make_modes(int fd, struct termios *tiop) /* Store input and output baud rates. */ baud = speed_to_baud(cfgetospeed(&tio)); - buffer_put_char(&buf, tty_op_ospeed); + buffer_put_char(&buf, TTY_OP_OSPEED); buffer_put_int(&buf, baud); baud = speed_to_baud(cfgetispeed(&tio)); - buffer_put_char(&buf, tty_op_ispeed); + buffer_put_char(&buf, TTY_OP_ISPEED); buffer_put_int(&buf, baud); /* Store values of mode flags. */ #define TTYCHAR(NAME, OP) \ buffer_put_char(&buf, OP); \ - put_arg(&buf, special_char_encode(tio.c_cc[NAME])); + buffer_put_int(&buf, special_char_encode(tio.c_cc[NAME])); #define TTYMODE(NAME, FIELD, OP) \ buffer_put_char(&buf, OP); \ - put_arg(&buf, ((tio.FIELD & NAME) != 0)); + buffer_put_int(&buf, ((tio.FIELD & NAME) != 0)); #include "ttymodes.h" @@ -333,10 +320,7 @@ tty_make_modes(int fd, struct termios *tiop) end: /* Mark end of mode data. */ buffer_put_char(&buf, TTY_OP_END); - if (compat20) - packet_put_string(buffer_ptr(&buf), buffer_len(&buf)); - else - packet_put_raw(buffer_ptr(&buf), buffer_len(&buf)); + packet_put_string(buffer_ptr(&buf), buffer_len(&buf)); buffer_free(&buf); } @@ -351,19 +335,10 @@ tty_parse_modes(int fd, int *n_bytes_ptr) int opcode, baud; int n_bytes = 0; int failure = 0; - u_int (*get_arg)(void); - int arg_size; - if (compat20) { - *n_bytes_ptr = packet_get_int(); - if (*n_bytes_ptr == 0) - return; - get_arg = packet_get_int; - arg_size = 4; - } else { - get_arg = packet_get_char; - arg_size = 1; - } + *n_bytes_ptr = packet_get_int(); + if (*n_bytes_ptr == 0) + return; /* * Get old attributes for the terminal. We will modify these @@ -382,9 +357,7 @@ tty_parse_modes(int fd, int *n_bytes_ptr) case TTY_OP_END: goto set; - /* XXX: future conflict possible */ - case TTY_OP_ISPEED_PROTO1: - case TTY_OP_ISPEED_PROTO2: + case TTY_OP_ISPEED: n_bytes += 4; baud = packet_get_int(); if (failure != -1 && @@ -392,9 +365,7 @@ tty_parse_modes(int fd, int *n_bytes_ptr) error("cfsetispeed failed for %d", baud); break; - /* XXX: future conflict possible */ - case TTY_OP_OSPEED_PROTO1: - case TTY_OP_OSPEED_PROTO2: + case TTY_OP_OSPEED: n_bytes += 4; baud = packet_get_int(); if (failure != -1 && @@ -404,13 +375,13 @@ tty_parse_modes(int fd, int *n_bytes_ptr) #define TTYCHAR(NAME, OP) \ case OP: \ - n_bytes += arg_size; \ - tio.c_cc[NAME] = special_char_decode(get_arg()); \ + n_bytes += 4; \ + tio.c_cc[NAME] = special_char_decode(packet_get_int()); \ break; #define TTYMODE(NAME, FIELD, OP) \ case OP: \ - n_bytes += arg_size; \ - if (get_arg()) \ + n_bytes += 4; \ + if (packet_get_int()) \ tio.FIELD |= NAME; \ else \ tio.FIELD &= ~NAME; \ @@ -424,51 +395,21 @@ tty_parse_modes(int fd, int *n_bytes_ptr) default: debug("Ignoring unsupported tty mode opcode %d (0x%x)", opcode, opcode); - if (!compat20) { - /* - * SSH1: - * Opcodes 1 to 127 are defined to have - * a one-byte argument. - * Opcodes 128 to 159 are defined to have - * an integer argument. - */ - if (opcode > 0 && opcode < 128) { - n_bytes += 1; - (void) packet_get_char(); - break; - } else if (opcode >= 128 && opcode < 160) { - n_bytes += 4; - (void) packet_get_int(); - break; - } else { - /* - * It is a truly undefined opcode (160 to 255). - * We have no idea about its arguments. So we - * must stop parsing. Note that some data - * may be left in the packet; hopefully there - * is nothing more coming after the mode data. - */ - logit("parse_tty_modes: unknown opcode %d", - opcode); - goto set; - } + /* + * SSH2: + * Opcodes 1 to 159 are defined to have a uint32 + * argument. + * Opcodes 160 to 255 are undefined and cause parsing + * to stop. + */ + if (opcode > 0 && opcode < 160) { + n_bytes += 4; + (void) packet_get_int(); + break; } else { - /* - * SSH2: - * Opcodes 1 to 159 are defined to have - * a uint32 argument. - * Opcodes 160 to 255 are undefined and - * cause parsing to stop. - */ - if (opcode > 0 && opcode < 160) { - n_bytes += 4; - (void) packet_get_int(); - break; - } else { - logit("parse_tty_modes: unknown opcode %d", - opcode); - goto set; - } + logit("parse_tty_modes: unknown opcode %d", + opcode); + goto set; } } } diff --git a/ttymodes.h b/ttymodes.h index 14e177cefc31..24f07560c9fd 100644 --- a/ttymodes.h +++ b/ttymodes.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ttymodes.h,v 1.15 2016/05/03 09:03:49 dtucker Exp $ */ +/* $OpenBSD: ttymodes.h,v 1.16 2017/04/30 23:26:54 djm Exp $ */ /* * Author: Tatu Ylonen @@ -38,22 +38,13 @@ */ /* - * SSH1: - * The tty mode description is a stream of bytes. The stream consists of + * The tty mode description is a string, consisting of * opcode-arguments pairs. It is terminated by opcode TTY_OP_END (0). - * Opcodes 1-127 have one-byte arguments. Opcodes 128-159 have integer - * arguments. Opcodes 160-255 are not yet defined, and cause parsing to - * stop (they should only be used after any other data). + * Opcodes 1-159 have uint32 arguments. + * Opcodes 160-255 are not yet defined and cause parsing to stop (they + * should only be used after any other data). * - * SSH2: - * Differences between SSH1 and SSH2 terminal mode encoding include: - * 1. Encoded terminal modes are represented as a string, and a stream - * of bytes within that string. - * 2. Opcode arguments are uint32 (1-159); 160-255 remain undefined. - * 3. The values for TTY_OP_ISPEED and TTY_OP_OSPEED are different; - * 128 and 129 vs. 192 and 193 respectively. - * - * The client puts in the stream any modes it knows about, and the + * The client puts in the string any modes it knows about, and the * server ignores any modes it does not know about. This allows some degree * of machine-independence, at least between systems that use a posix-like * tty interface. The protocol can support other systems as well, but might diff --git a/umac.c b/umac.c index 6eb55b26ef7f..9f2187c9af98 100644 --- a/umac.c +++ b/umac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: umac.c,v 1.11 2014/07/22 07:13:42 guenther Exp $ */ +/* $OpenBSD: umac.c,v 1.12 2017/05/31 08:09:45 markus Exp $ */ /* ----------------------------------------------------------------------- * * umac.c -- C Implementation UMAC Message Authentication @@ -203,6 +203,8 @@ static void kdf(void *bufp, aes_int_key key, UINT8 ndx, int nbytes) aes_encryption(in_buf, out_buf, key); memcpy(dst_buf,out_buf,nbytes); } + explicit_bzero(in_buf, sizeof(in_buf)); + explicit_bzero(out_buf, sizeof(out_buf)); } /* The final UHASH result is XOR'd with the output of a pseudorandom @@ -227,6 +229,7 @@ static void pdf_init(pdf_ctx *pc, aes_int_key prf_key) /* Initialize pdf and cache */ memset(pc->nonce, 0, sizeof(pc->nonce)); aes_encryption(pc->nonce, pc->cache, pc->prf_key); + explicit_bzero(buf, sizeof(buf)); } static void pdf_gen_xor(pdf_ctx *pc, const UINT8 nonce[8], UINT8 buf[8]) @@ -991,6 +994,7 @@ static void uhash_init(uhash_ctx_t ahc, aes_int_key prf_key) kdf(ahc->ip_trans, prf_key, 4, STREAMS * sizeof(UINT32)); endian_convert_if_le(ahc->ip_trans, sizeof(UINT32), STREAMS * sizeof(UINT32)); + explicit_bzero(buf, sizeof(buf)); } /* ---------------------------------------------------------------------- */ @@ -1200,6 +1204,7 @@ int umac_delete(struct umac_ctx *ctx) if (ctx) { if (ALLOC_BOUNDARY) ctx = (struct umac_ctx *)ctx->free_ptr; + explicit_bzero(ctx, sizeof(*ctx) + ALLOC_BOUNDARY); free(ctx); } return (1); @@ -1227,6 +1232,7 @@ struct umac_ctx *umac_new(const u_char key[]) aes_key_setup(key, prf_key); pdf_init(&ctx->pdf, prf_key); uhash_init(&ctx->hash, prf_key); + explicit_bzero(prf_key, sizeof(prf_key)); } return (ctx); diff --git a/utf8.c b/utf8.c index dead79b8a252..bc131385f536 100644 --- a/utf8.c +++ b/utf8.c @@ -1,4 +1,4 @@ -/* $OpenBSD: utf8.c,v 1.5 2017/02/19 00:10:57 djm Exp $ */ +/* $OpenBSD: utf8.c,v 1.7 2017/05/31 09:15:42 deraadt Exp $ */ /* * Copyright (c) 2016 Ingo Schwarze * @@ -61,7 +61,8 @@ dangerous_locale(void) { loc = nl_langinfo(CODESET); return strcmp(loc, "US-ASCII") != 0 && strcmp(loc, "UTF-8") != 0 && - strcmp(loc, "ANSI_X3.4-1968") != 0 && strcmp(loc, "646") != 0; + strcmp(loc, "ANSI_X3.4-1968") != 0 && strcmp(loc, "646") != 0 && + strcmp(loc, "") != 0; } static int @@ -75,7 +76,7 @@ grow_dst(char **dst, size_t *sz, size_t maxsz, char **dp, size_t need) tsz = *sz + 128; if (tsz > maxsz) tsz = maxsz; - if ((tp = realloc(*dst, tsz)) == NULL) + if ((tp = recallocarray(*dst, *sz, tsz, 1)) == NULL) return -1; *dp = tp + (*dp - *dst); *dst = tp; diff --git a/version.h b/version.h index c86e2097c715..e093f623b227 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ -/* $OpenBSD: version.h,v 1.79 2017/03/20 01:18:59 djm Exp $ */ +/* $OpenBSD: version.h,v 1.80 2017/09/30 22:26:33 djm Exp $ */ -#define SSH_VERSION "OpenSSH_7.5" +#define SSH_VERSION "OpenSSH_7.6" #define SSH_PORTABLE "p1" #define SSH_RELEASE SSH_VERSION SSH_PORTABLE diff --git a/xmalloc.c b/xmalloc.c index b58323677ee7..5cc0310a4766 100644 --- a/xmalloc.c +++ b/xmalloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xmalloc.c,v 1.33 2016/02/15 09:47:49 dtucker Exp $ */ +/* $OpenBSD: xmalloc.c,v 1.34 2017/05/31 09:15:42 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -77,6 +77,18 @@ xreallocarray(void *ptr, size_t nmemb, size_t size) return new_ptr; } +void * +xrecallocarray(void *ptr, size_t onmemb, size_t nmemb, size_t size) +{ + void *new_ptr; + + new_ptr = recallocarray(ptr, onmemb, nmemb, size); + if (new_ptr == NULL) + fatal("xrecallocarray: out of memory (%zu elements of %zu bytes)", + nmemb, size); + return new_ptr; +} + char * xstrdup(const char *str) { diff --git a/xmalloc.h b/xmalloc.h index e4992893276d..cf38ddfa48c5 100644 --- a/xmalloc.h +++ b/xmalloc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: xmalloc.h,v 1.16 2016/02/15 09:47:49 dtucker Exp $ */ +/* $OpenBSD: xmalloc.h,v 1.17 2017/05/31 09:15:42 deraadt Exp $ */ /* * Author: Tatu Ylonen @@ -20,6 +20,7 @@ void ssh_malloc_init(void); void *xmalloc(size_t); void *xcalloc(size_t, size_t); void *xreallocarray(void *, size_t, size_t); +void *xrecallocarray(void *, size_t, size_t, size_t); char *xstrdup(const char *); int xasprintf(char **, const char *, ...) __attribute__((__format__ (printf, 2, 3)))